Error in building MPI program - fortran

I'm new to MPI. I'm trying to write a program for calculating PI using MPI and FORTRAN. But when I try to build the program I get the following messages.
make all
gfortran -O2 -g \
-o bin/MpiTest.exe \
src/MpiTest.f -fno-range-check
C:/Program Files/MicrosoftMPI/Inc/mpif.h:344.38:
Included at src/MpiTest.f:11:
PARAMETER (MPI_AINT=z'4c00043b')
1
Error: PARAMETER attribute of 'mpi_aint' conflicts with PARAMETER attribute at (1)
C:/Program Files/MicrosoftMPI/Inc/mpif.h:359.35:
Included at src/MpiTest.f:11:
PARAMETER (MPI_ADDRESS_KIND=INT_PTR_KIND())
1
Error: Function 'int_ptr_kind' in initialization expression at (1) must be an intrinsic function
make: *** [all] Error 1
Can anyone help me here ?
P.S :
PROGRAM CalculatePI
include "C:/Program Files/MicrosoftMPI/Inc/mpif.h"
INTEGER :: i = 0, nThrows = 0, nSuccess = 0, ierror =0, numOfProcessors=0,myID=0
REAL :: x = 0, y = 0, results = 0
INTEGER :: Counter = 0
call mpi_init(ierror)
call mpi_comm_rank(MPI_COMM_WORLD, myID, ierror)
call mpi_comm_size(MPI_COMM_WORLD, numOfProcessors, ierror)
....

INT_PTR_KIND is an Intel Fortran compiler extension function; that is, it is not a Fortran intrinsic. The second of the error messages that you report indicates that gfortran is baulking at compiling code which contains references to a function it can't find. I guess the first error arises from the same problem, you are trying to compile with the 'wrong' compiler.
As Alexander Vogt has suggested you might make better progress using a compiler wrapper such as mpif90, but it has to be the right wrapper, the one which calls gfortran and links with the MS MPI library. Whether that wrapper exists I do not know, but look for it under C:/Program Files/MicrosoftMPI/.
However, since those errors emanate from the mpif.h file you have included you'll also have to find a corresponding include file for compiling with gfortran. I don't use MS MPI but it won't surprise me if you find that it only provides tools, libraries and include files for compilation with Intel Fortran.

You should not compile your MPI code with gfortran alone. Instead, use the wrapper provided by your MPI library. Typically it is called mpif90.
Thanks to High Performance Mark for the clarifications.

Related

`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.

use fftw3 with gfortran included in TDM-GCC-64

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.

MS-MPI and MinGW Fortran

This is simple fortran90 program testing MPI.
I would like to compile it on MS Windows platform using MinGW64 Fortran and the known MS-MPI package.
However, it's not working due to missing "mpi.mod". When I replace the use mpi with include 'mpif.h', it's giving other errors (below).
Any help, please ? Does the MS-MPI suite cooperate with the MinGW gfortran ?
PS1:
Working with MS-MPI and MinGW gfortran is not an easy task, https://social.microsoft.com/Forums/en-US/245dcda4-7699-494f-bbe1-b76eb19e53da/linking-msmpi-with-mingw-gfortran?forum=windowshpcmpi
C:\Users\milias\Documents\Dirac\software\autocmake-devel\ms-mpi>gfortran -fno- range-check -c example.f90
mpif.h:344.38:
Included at example.f90:4:
PARAMETER (MPI_AINT=z'4c00043b')
1
Error: PARAMETER attribute of 'mpi_aint' conflicts with PARAMETER attribute at (1)
mpif.h:359.35:
Included at example.f90:4:
PARAMETER (MPI_ADDRESS_KIND=INT_PTR_KIND())
1
Error: Function 'int_ptr_kind' in initialization expression at (1) must be an intrinsic function
solved here, I apologize for the duplicate.
https://github.com/scisoft/autocmake/issues/85#issue-102874399

Why does 'use mpi' fail with mpif90

In order to compile MPI code in gfortran I have to use the syntax
include mpif.h
in my code instead of
use mpi
Several websites indicate that this syntax is for Fortran 77 however, I am using gfortran gcc version 4.7.2 (Debian 4.7.2-5) and mpfi90 for MPICH2 version 1.4.1p1.
The command line
mpif90 test1.f90 -o test1.exe
produces the following error
test1.f90:4.8: use mpi 1 Fatal Error: Parse error when checking module version for file 'mpi.mod' opened at (1)
test1.f90 (from Coursera course on HPC)
program test1
use mpi !(fails to compile)
implicit none
include 'mpif.h' !(this works)
integer :: ierr, numprocs, proc_num
call mpi_init(ierr)
call mpi_comm_size(MPI_COMM_WORLD, numprocs, ierr)
call mpi_comm_rank(MPI_COMM_WORLD, proc_num, ierr)
print *, 'Hello from Process number', proc_num, &
' of ', numprocs, ' processes'
call mpi_finalize(ierr)
end program test1
Another option I often encounter is when the Fortran compiler used to build the MPI library is not compatible with your current Fortran compiler. Then the problem is the incompatibility of the .mod files. Gfortran is more susceptible to this, than say Intel Fortran, because it changes the module format more often.
Depending on how MPICH2 was compiled, perhaps the F90 interface wasn't built. That tends to happen depressingly often when using packages built by C-heads.

How to link a fortran subroutine to a cpp main program?

I am trying to compile a c++ program but it does not work.
At first, I should said that c++ is not a language I really know, I use Fortran. Anyway, the main c++ program calls a fortran subroutine. I can compile this subroutine but when I want to compile the c++ program there is a link error.
The real program is just huge and calls many subroutines, so I did a simple test (simple program calling just one subroutine) and it does not work as well! When I want to create the .x my subroutine is undefined.
Here is the c++ program (test-TQINIT.cpp) and the subroutine (TQINIT.f).
test-TQINIT.cpp:
#include <iostream>
using namespace std;
extern "C"
{
void TQINIT_(int*, int*);
}
main()
{ int NWG;
NWG=80000;
int *IWSG = new int[NWG];
TQINIT_(IWSG,&NWG);
}
TQINIT.f:
SUBROUTINE TQINIT(IWSG,NWG)
IMPLICIT NONE
INTEGER NWG
INTEGER IWSG(NWG)
LOGICAL TQG2ERR
INTEGER IERR
CALL TQRSERR
CALL TQINI(NWG,IWSG)
IF (TQG2ERR(IERR)) THEN
WRITE(6,*)'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!'
WRITE(6,*)'ERROR INITIALIZING (TQINIT) !!!'
WRITE(6,*)'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!'
STOP
ENDIF
END
I compile the subroutine using:
gfortran -c TQINIT.f
and get a TQINIT.o
Then I compile the main program using:
g++ -c test-TQINIT.cpp
and get a test-TQINIT.o.
Then for create the .x I use (TQINIT.f need the library):
g++ test-TQINIT.o TQINIT.o -L/usr/local/thermocalc/3.0/SDK/TQ8 -ltq-linux-x86_64-gfortran44-8 -o test-TQINIT.x
This is what I get:
test-TQINIT.o: In function `main':
test-TQINIT.cpp:(.text+0x33): undefined reference to `TQINIT_'
collect2: ld returned 1 exit status
I hope someone will be able to help me.
Thank you by advance.
Fortran is case-insensitive, and the name of the subroutines in the object file normally (as far as I know) end up in lowercase with an underscore, so yours is probably named tqinit_ and not TQINIT_, so your call in C++ should be lowercase.
You can verify the name in the object file with the objdump -t TQINIT.o command given in Alexander Vogt's answer, or the simpler nm TQINIT.o which is more terse.
If you use the ISO_C_BINDING in Fortran, you will have control over the precise routine names that will be seen by the other language, e.g., case, no underscores. You can also declare the arguments so that consistency with C/C++ will be guaranteed. For more on this topic, see https://stackoverflow.com/questions/tagged/fortran-iso-c-binding
I'm no expert on mixing C and Fortran, but I have always linked the Fortran Code directly using
g++ test-TQINIT.cpp TQINIT.o -L/usr/local/thermocalc/3.0/SDK/TQ8 \
-ltq-linux-x86_64-gfortran44-8 -o test-TQINIT.x
instead of compiling those two files separately and then linking... Perhaps this helps (although your way should work as well, at least it does with the simple example I tried).
BTW:
You can find out how the functions in your Fortran object are called by issuing
objdump -t TQINIT.o
This should give you the correct function name to call.