use fftw3 with gfortran included in TDM-GCC-64 - fortran

I am trying to use FFTW3 with gfortran compiler included in the TDM-GCC-64 suite in Windows 7 platform.
I have downloaded "fftw-3.3.4-dll64.zip" from the following page:
http://www.fftw.org/install/windows.html
I also created a fortran module described in the following tutorial:
http://www.fftw.org/doc/Defining-an-FFTW-module.html
Now, I tried to compile the following fortrans program
program test
use FFTW3
implicit none
integer N
parameter(N=4)
integer*8 plan
double complex in, out
dimension in(N),out(N)
integer i
write(*,*) 'Input array:'
do i = 1,N,1
in(i) = dcmplx(float(i),float(i+1))
write(*,*) ' in(',i,') = ',in(i)
enddo
call dfftw_plan_dft_1d ( plan, N, in, out, FFTW_FORWARD, FFTW_ESTIMATE )
call dfftw_execute ( plan )
write(*,*) 'Output array:'
do i = 1,N,1
write(*,*) ' out(',i,') = ',out(i)
enddo
call dfftw_destroy_plan ( plan )
call dfftw_plan_dft_1d ( plan, N, out, in, FFTW_FORWARD, FFTW_ESTIMATE )
call dfftw_execute ( plan )
write(*,*) 'Output array after inverse FFT:'
do i = 1,N,1
write(*,*) ' ',N,' * in(',i,') = ',in(i)
enddo
call dfftw_destroy_plan ( plan )
end
I tried to compile but the a couple of error messages popped up:
undefined reference to dfftw_plan_dft_1d_'
undefined reference todfftw_execute_'
...
The command used for compiling is:
gfortran test.f90 -ffree-form -o test_fftw.exe
I searched web up and down but have not found solutions to the problem. Could anyone help me out here? Thanks!!!

You need to learn the basics of compiling and linking programs with GCC
This tutorial refers to the GCC C compiler, gcc, and C++ compiler, g++, but the principles are the same for the Fortran compiler, gfortran.
Your program invokes functions, like dfftw_plan_dft_1d that are not defined
in your code but in the fftw3 library. You must therefore tell gfortran
to link that library with your program, after it is compiled, or no definitions will be found for
these functions, and no executable can be built. Instead, the linkage
fails with the undefined reference errors you are seeing.
The command you have used to build the program:
gfortran test.f90 -ffree-form -o test_fftw.exe
attempts to compile and link the program in a single command. You can do this,
if you clearly understand the underlying separate processes of compiling
and linking. If you don't, you should follow the better practice of compiling first,
and if that is successful, then linking. The command you have used fails in
its linkage step because it does not tell the linker that the fftw3 library
is needed (or where to find it) so no attempt is made to find it and link it.
You say you have downloaded fftw-3.3.4-dll64.zip. I presume you have
unzipped it somewhere on your system. Let's say you unzipped it to C:\fftw-3.3.4-dll64.
You also say you have made an FFTW3 module that apparently is being used successfully.
In that case, compile your program first:
gfortran -c -o test.o test.f90
generating an object file test.o. The option -c tells gfortran to compile only,
and not to link. (You do not need to specify --ffree-form: the file-extension .f90
implies it).
Next, link the object file test.o with the fttw3 library, to make an executable
program test_fftw.exe:
gfortran -o test_fftw.exe test.o -LC:\fftw-3.3.4-dll64 -lfftw3-3
The linker option:
-LC:\fftw-3.3.4-dll64
tells the linker to add C:\fftw-3.3.4-dll64 (where you unzipped the package)
to the list of directories that it will search to find libraries. And the linker option -lfftw3-3 tells it to link a library that matches the identifier fftw3-3. On Windows, the GCC linker
will match a library identfier name with any of the filenames:
libname.a (a static library)
libname.dll (a shared library)
name.dll (also a shared library)
name.lib (an import library for a shared library)
So, since C:\fftw-3.3.4-dll64 contains the shared library libfftw3-3.dll,
the linker will identify it in that directory as the one required by -lfftw3-3
Now, unless there are other problems, you program will link and you will have
an executable test_fftw.exe, which will run, provided that libfftw3-3.dll
can be found, at runtime, in one of the places where the Windows
loader will look for it.

Related

How to link to -llapack when compiling fortran using gfortran

I am trying to compile a simple program, example.f90
program example
use dsyevd
implicit none
end program example
I am compiling using the command
gfortran -llapack example.f90
However this compilation returns the message
Fatal Error: Cannot open module file 'dsyevd.mod' for reading at (1): No such file or directory
dsyevd is a function in lapack. I have installed intel-mkl onto my computer which contains lapack95. Any advice on how to link my compile to these libraries would be hugely appreciated.
Thank you!
Lapack does not contain any module called dsyevd, so you cannot use it. It is a subroutine so it should be called.
Using -llapack is OK for the default Lapack pre-installed in your Linux distribution. For MKL you must use the appropriate options from the Link Advisor.

Naming of symbols in Fortran shared library, intel vs gcc?

Is there a way to control the naming of symbols in shared libraries? Specifically, I've been using GCC for a project where we access shared library through C-Types in Python. This works great, however recently I've been working with a system where the Intel compiler is suggested. I can build the shared object just fine but I find the symbols have a slightly different naming convention as compared to intel. Specifically when I compile with gcc the symbol names look like:
__test_function_MOD_read_a_file
the Intel compiled shared object has the symbol names like:
test_function_mp_read_a_file__
Is there a way to force consistency of the naming or at least change the name of the symbols after the fact?
For example consider the following bit of code test_function.f90
MODULE test_function
CONTAINS
SUBROUTINE read_a_file
PRINT *,'I did a thing!'
END SUBROUTINE
END
The compile line should look something like
gfortran -fPIC -c test_function.f90
gfortran -shared -o libtest_function.so test_function.o
Both compilers are mangling the names of the subprograms contained in the module. The Fortran standard does not mandate any naming convention. You can prevent the name mangling by using the ISO C Binding feature of Fortran to give the subprogram a specific name. For example,
module bar
contains
function fun(x) bind(c, name='foo')
real fun, x
fun = x
end function fun
function goo(x)
real goo, x
goo = x
end function goo
end module bar
When compiled with gfortran the resulting object file contains
gfortran -c a.f90
nm a.o
00000000 T __bar_MOD_goo
00000013 T foo
Thus, you can reference functionfun as foo in the library. You'll probably also want to use the types defined by the iso_c_binding module.

`undefined reference to `sgtsv_'` when compiling a tridiagonal solver

I'm working on a problem for one of my computing courses and I was getting stuck in an error after trying to work through it for some time.
Specifically, I'm working on this Fortran routine:
program linsolve_sgtsv
implicit none
integer, parameter :: lda=10,ldb=lda,nrhs=1
real :: dl(lda-1),d(lda),du(lda-1),b(ldb,nrhs)
integer :: n,info
n = 10
dl(1:n-1) = 1+(1/11); d(1:n) = 2; du(1:n-1) = 1-(1/11)
b(1:n,1) = (/1,1,1,1,1,1,1,1,1,1/)
call sgtsv(n,nrhs,dl,d,du,b,ldb,info)
if (info==0) then
print *, '--- x is ----------------'
print '(g22.16)', b(1:n,1)
else
print *, 'info = ',info
end if
end program linsolve_sgtsv
This routine solves linear systems using gaussian elimination when the matrices are tridiagonal.
However, when I try to create a makefile using:
gfortran linsolve_sgtsv.f90 -o linsolve.f90
I get the following errors:
tmp/ccCiRHve.o: In function `MAIN__':
linsolve_sgtsv.f90:(.text+0x100): undefined reference to `sgtsv_'
collect2: error: ld returned 1 exit status
I can't find any direct duplicate. Many people have similar problems, but they usually know a bit more and your question is more basic.
The tridiagonal solver sgtsv() is not a Fortran built-in subroutine. It is provided in a library called LAPACK and many other implementations (e.g., MKL). That means you must tell the compiler it should include (link) that library.
That is done by adding -llapack (-l means "link" and lapack is the name of the library which is stored in a file called liblapack.so or liblapack.a) at the end of the compile command.
You must have his library installed in your computer for the link flag to work. In many Linux distributions it is included in the repositories.
The correct line would be
gfortran linsolve_sgtsv.f90 -o linsolve -llapack
If the library (liblapack.a or liblapack.so) is installed in some directory the compiler can't see, you must use
gfortran linsolve_sgtsv.f90 -o linsolve -L/path/to/liblapack -llapack
See also gfortran LAPACK "undefined reference" error and your compiler's manual for more.
Notice I did -o linsolve instead of -o linsolve.f90. It is a very bad idea to name your executable file with a .f90 extension. Only Fortran source files should be named .f90.
There will be more problems in your code. They will appear when you start to test it. For example, yoy do
(1/11)
this will not return the mathematical result of 1.0/11.0, it will return 0. Learn about integer division in Fortran. See Why are the elements of an array formatted as zeros when they are multiplied by 1/2 or 1/3? and Simple program, that only produce zeros, bug?
If you will find more problems after you can run your code, you can ask a new question.
I recommend to compile your programs with -g -fcheck=all -Wall to find more bugs and errors more easily.

Undefined reference to gfortran_runtime_error

I would like to run a model is written Fortran90 under Ubuntu 14.04. I use gfortran 95 compiler (gfortran 4:4.8.2-1ubuntu6). The required netCDF libraries (netCDF C and Fortran netCDF) are installed as suggested in: http://www.unidata.ucar.edu/software/netcdf/docs/. The netcdf is built as shared library so libnetcdf.so and libnetcff.so files there are in the library directory. The libgfortran3 4.8.2-19ubuntu1 is installed for GNU fortran application linked against the shared library.
The LDFLAGS is set in the compiler_options.inc file by the following way:
INCDF=-I$(NCPATH)/include
LNCDF=-L$(NCPATH)/lib -lnetcdff -lnetcdf
LDFLAGS=$(INCDF) $(LNCDF)
When I compile the model I get the following messages:
/home/Beata/kid_a_setup/src/test_cases_2d.f90:1446: undefined reference to `_gfortran_runtime_error_at
Could someone explain me what causes the error and how I can fix it?
undefined reference to _gfortran_runtime_error_at means that the libgfortran library has not been found.
Either your system is misconfigured (can you compile, link and run a "Hello, world" program using gfortran?), or you are using the gcc command for linking instead of gfortran for linking. gcc does not know about the libgfortran library, where _gfortran_runtime_error_at is defined.

resolving non-unique symbols between c++ wrapper libraries for fortran subroutines

I am working with two sets of FORTRAN code, for example, codeA.f and codeB.f. In each set of code there are subroutines with the same name, but which perform significantly different tasks (as well as common blocks).
codeA.f:
subroutine init
c do something here ...
end
codeB.f:
subroutine init
c do something else here ...
end
I create two C++ wrappers for both routines (wrapperB is identical, but swap B for A).
wrapperA.cpp:
namespace codeA {
extern "C"{void init_();}
void init() {init_();}
}
wrapperA.h:
namespace codeA {
init();
}
I then compile the two wrappers into shared libraries.
Makefile:
codeA.o : codeA.F
g77 -fno-automatic -fPIC -O3 -c codeA.f -o codeA.o
wrapperA.o : wrapperA.cpp
g++ -fPIC -c wrapperA.cpp -o wrapperA.o
libwrapperA.so : codeA.o wrapperA.o
g++ -fPIC -shared -lg2c codeA.o wrapperA.o -o libwrapperA.so
Finally, I want to be able to call the two different subroutines from the same program.
main.cpp:
#include "wrapperA.h"
#include "wrapperB.h"
main {
wrapperA::init();
wrapperB::init();
}
The main program is linked against the two shared wrapper libraries.
Makefile:
main : main.cpp
g++ main.cpp -I. -L. -lwrapperA -lwrapperB -o main
Everything compiles and there are no complaints. However, when the program "main" is run, the init() commands perform the same action, dictated by which of the wrapper libraries was linked against first. However, if I link against only one of the libraries, the linker complains about missing symbols.
I have two question about this:
a) Is it possible to link against two different FORTRAN routines using only namespaces or some similar method to what I am doing? If so, what am I doing wrong?
b) If a) is not possible, is it possible to resolve the conflicts by instructing the compiler to append the symbols with some unique identifier when creating the FORTRAN objects (I am using gcc version 4.1.2 20080704 (Red Hat 4.1.2-51))?
Thanks for any insight into this.
Your compile commands show the use of g77, which is no longer maintained and also implies the use of a very old version of Fortran (i.e., FORTRAN 77). You are also using an old version of gcc. If you use gcc and gfortran of version 4.3 or higher -- preferably 4.4 or higher -- then you can use the Fortran 2003 ISO C Binding to solve your problem. In the Fortran code you can assign externally visible names to the routines with the "bind" option of the ISO C Binding. Just assign different "bind" names to the two routines. Then they won't clash at the library & linker level:
In one Fortran file use
subroutine init (stuff...) bind (C, name="init_V1")
and the other file
subroutine init (stuff...) bind (C, name="init_V2")
and the routines will be visible to C, C++, the linker, etc. as init_V1 and init_V2 without clashing.
Have a look at this SO question, which is very similar to your problem : Static and shared library symbol conflicts?
Basically, you have two shared libraries defining different symbols : wrapperA::init() and wrapperB::init() ; but also conflicting symbols : _init__(). So when the linker resolves, it use the first of the conflicting symbol it find.
If you remove the unneeded external visibility of _init__() in your libraries by using the techniques given in the SO question : http://www.gnu.org/software/gnulib/manual/html_node/Exported-Symbols-of-Shared-Libraries.html, then I think you will have solved your problem. Each wrapper::init() will then call internally it's proper _init__() without any conflict.