Interlanguage Programming
This page provides examples of compilation and running scripts when mixing C/C++ with Fortran codes.
C/MPI Main Calling Fortran Subroutine
Here is a full example of a parallel C code using MPI which calls a Fortran subroutine. The Fortran subroutine sets a number of data values based on the MPI task ID. The code is compiled and run using the batch system.
C Source Code
% cat cmainmpi.c
#include "mpi.h"
int main(int argc, char* argv[]) {
char bool1, letter1;
int numint1, numint2;
float numfloat1;
double numdoub1;
short numshor1;
extern void forts_();
int myid, numprocs;
MPI_Init(&argc,&argv);
MPI_Comm_size(MPI_COMM_WORLD,&numprocs);
MPI_Comm_rank(MPI_COMM_WORLD,&myid);
forts_(&bool1, &letter1, &numint1, &numint2, &numfloat1,
&numdoub1, &numshor1, &myid, 1);
printf(" Hello from proc %d of %d; data values: %s %c %d %d %3.1f %.0f %d\n",
myid, numprocs, bool1?"TRUE":"FALSE", letter1, numint1,
numint2, numfloat1, numdoub1, numshor1);
MPI_Finalize();
}
Fortran Source Code
% cat forts.f
subroutine forts(bool1,letter1,numint1,numint2,numfloat1,
& numdoub1,numshor1,numtask)
logical*1 bool1
character letter1
integer numint1, numint2, numtask
double precision numdoub1
real numfloat1
integer*2 numshor1
bool1 = .true.
if (numtask .ne. 2*(numtask/2)) bool1 = .false.
letter1 = "y"
numint1 = 11*numtask
numint2 = numtask
numdoub1 = 902
numfloat1 = 39.6 + (0.1*numtask)
numshor1 = 299
return
end
Batch Job Script
% cat runhello #PBS -N hellojob #PBS -q debug #PBS -l mppwidth=4 #PBS -l walltime=00:05:00 #PBS -e hellojob.out #PBS -j eo cd $PBS_O_WORKDIR cc -c cmainmpi.c ftn -o cftnmpi -Mnomain cmainmpi.o forts.f aprun -n 4 ./cftnmpi
Output File
% cat hellojob.out
Warning: no access to tty (Bad file descriptor).
Thus no job control in this shell.
forts.f:
Hello from proc 0 of 4; data values: TRUE y 0 0 39.6 902 299
Hello from proc 3 of 4; data values: FALSE y 33 3 39.9 902 299
Hello from proc 2 of 4; data values: TRUE y 22 2 39.8 902 299
Hello from proc 1 of 4; data values: FALSE y 11 1 39.7 902 299
Application 8551030 resources: utime ~0s, stime ~0s
C++/MPI Main Calling Fortran Subroutine
Here is a full example of a parallel C++ code using MPI which calls a Fortran subroutine. The Fortran subroutine sets a number of data values based on the MPI task ID. The code is compiled and run using the batch system.
C++ Source Code
% cat cpmain.C
#include <mpi.h>
#include <iostream>
using namespace std;
extern "C" { extern void forts_(char *,char *,int *,int *,
float *,double *,short *); }
int main (int argc, char* argv[])
{
char bool1, letter1;
int numprocs, myid;
float numfloat1;
double numdoub1;
short numshor1;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD,&numprocs);
MPI_Comm_rank(MPI_COMM_WORLD,&myid);
forts_(&bool1,&letter1,&myid,&numprocs,&numfloat1,&numdoub1,&numshor1);
cout << " bool1 = ";
bool1?cout << "TRUE ":cout << "FALSE ";
cout << "; letter1 = " << letter1 << "; myid = " << myid << " numprocs = " << numprocs;
cout << " myid/numprocs = " << numfloat1 << endl;
cout << " numdoub1 = " << numdoub1 << " numshor1 = " << numshor1 << endl;
MPI_Finalize();
}
Fortran Source Code
% cat forts.f
subroutine forts
& (bool1,letter1,numint1,numint2,numfloat1,numdoub1,numshor1)
logical*1 bool1
character letter1
integer numint1, numint2
double precision numdoub1
real numfloat1
integer*2 numshor1
bool1 = .true.
if (numint1 .ne. 2*(numint1/2)) bool1 = .false.
letter1 = "v"
numdoub1 = 902
numfloat1 = (1.0*numint1)/(1.0*numint2)
numshor1 = 299
return
end
Batch Job Script
% cat runftncpp #PBS -N ftncpp #PBS -q debug #PBS -l mppwidth=4 #PBS -l walltime=00:01:00 #PBS -e ftncpp.out #PBS -j eo cd $PBS_O_WORKDIR ftn -c forts.f CC -o cppftn forts.o cpmain.C aprun -n 4 ./cppftn
Output File
% cat ftncpp.outWarning: no access to tty (Bad file descriptor).
Thus no job control in this shell.
cpmain.C:
bool1 = TRUE ; letter1 = v; myid = 0 numprocs = 4 myid/numprocs = 0
bool1 = FALSE ; letter1 = v; myid = 1 numprocs = 4 myid/numprocs = 0.25
bool1 = FALSE ; letter1 = v; myid = 3 numprocs = 4 myid/numprocs = 0.75
bool1 = TRUE ; letter1 = v; myid = 2 numprocs = 4 myid/numprocs = 0.5
numdoub1 = 902 numshor1 = 299
numdoub1 = 902 numshor1 = 299
numdoub1 = 902 numshor1 = 299
numdoub1 = 902 numshor1 = 299
Application 8551267 resources: utime ~0s, stime ~0s
C/MPI Main Calling Fortran/OpenMP Subroutine
Here is a full example of a parallel C code using MPI which calls a Fortran subroutine. The Fortran subroutine includes a multi-threaded parallel segment and sets a number of data values based on the MPI task ID and number of OpenMP threads. The code is compiled and run using the batch system.
The environment variable OMP_NUM_THREADS is used to control the number of threads in the OpenMP segment.
Use of OpenMP requires a particular set of options on the Fortran compiler line: ftn -mp=nonuma -Minfo=mp ....
The source code for the C main program is the same as shown above. The Fortran routine, the batch script, and the output for the mixed C/Fortran and mixed MPI/OpenMP example are shown below.
Fortran Source Code
% cat forts.f
subroutine forts2(bool1,letter1,numint1,numint2,numfloat1,
& numdoub1,numshor1,numtask)
logical*1 bool1
character letter1
integer numint1, numint2, numtask
integer nthreads, tid
integer OMP_GET_NUM_THREADS, OMP_GET_THREAD_NUM
double precision numdoub1
real numfloat1
integer*2 numshor1
bool1 = .true.
if (numtask .ne. 2*(numtask/2)) bool1 = .false.
letter1 = "y"
numint1 = 11*numtask
numint2 = numtask
numdoub1 = 902
numfloat1 = 39.6 + (0.1*numtask)
!$OMP PARALLEL PRIVATE(nthreads, tid)
tid = OMP_GET_THREAD_NUM()
IF (tid .EQ. 0) THEN
nthreads = OMP_GET_NUM_THREADS()
numshor1 = nthreads
ENDIF
!$OMP END PARALLEL
return
end
Batch Job Script
% cat runhello2 #PBS -N hellojob2 #PBS -q debug #PBS -l mppwidth=24 #PBS -l walltime=00:05:00 #PBS -e hellojob2.out #PBS -j eo cd $PBS_O_WORKDIR cc -c cmainmpi.c ftn -o cftnmpi -Mnomain -mp=nonuma -Minfo=mp cmainmpi.o forts.f setenv OMP_NUM_THREADS 6 aprun -n 4 -N 4 -S 1 -d 6 ./cftnmpi
Output File
% cat hellojob2.out
Warning: no access to tty (Bad file descriptor).
Thus no job control in this shell.
forts.f:
forts:
19, Parallel region activated
24, Parallel region terminated
Hello from proc 3 of 4; data values: FALSE y 33 3 39.9 902 6
Hello from proc 1 of 4; data values: FALSE y 11 1 39.7 902 6
Hello from proc 0 of 4; data values: TRUE y 0 0 39.6 902 6
Hello from proc 2 of 4; data values: TRUE y 22 2 39.8 902 6
Application 8551213 resources: utime ~0s, stime ~0s


