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