#Fortran
Copy the code below into mapreduce.f
.
c Here is the function used to calculate the energy
c of the passed ion
double precision function calc_energy(ref_x, ref_y, ref_z,
. ion_x, ion_y, ion_z)
implicit none
double precision ion_x, ion_y, ion_z
double precision ref_x, ref_y, ref_z
double precision r
r = sqrt( (ref_x - ion_x)**2 +
. (ref_y - ion_y)**2 +
. (ref_z - ion_z)**2 )
c The energy is just 1 / r
calc_energy = 1.0 / r
return
end
c You would need to fill in this subroutine to read
c in the array of ions
subroutine readArrayOfIons(ions_array, n_ions)
implicit none
integer i, n_ions
integer MAX_IONS
parameter(MAX_IONS = 1000)
double precision ions_array(MAX_IONS,3)
n_ions = 10
do i=1,10
ions_array(i,1) = 0.0
ions_array(i,2) = 0.0
ions_array(i,3) = i-1
enddo
end
program main
implicit none
include 'mpif.h'
integer i, n_ions
integer MAX_IONS
parameter(MAX_IONS = 1000)
integer rank, nprocs, err
integer num_calc, start, stop
double precision ions_array(MAX_IONS, 3)
double precision ion(3)
double precision total_energy, energy
double precision calc_energy
double precision ref_ion(3)
call MPI_Init(err)
call MPI_Comm_Size(MPI_COMM_WORLD, nprocs, err)
call MPI_Comm_Rank(MPI_COMM_WORLD, rank, err)
if (rank .eq. 0) then
ref_ion(1) = 1
ref_ion(2) = 2
ref_ion(3) = 3
if (nprocs .gt. 1) then
c send the reference ion to the other processes
call MPI_Bcast(ref_ion, 3, MPI_DOUBLE_PRECISION, 0,
. MPI_COMM_WORLD, err)
endif
call readArrayOfIons(ions_array, n_ions)
if (nprocs .gt. 1) then
c send the array of ions to the other processes
c (note that this would be more efficiently done with MPI_Scatter)
call MPI_Bcast(n_ions, 1, MPI_INTEGER, 0,
. MPI_COMM_WORLD, err)
do i=1,n_ions
ion(1) = ions_array(i,1)
ion(2) = ions_array(i,2)
ion(3) = ions_array(i,3)
call MPI_Bcast(ion, 3, MPI_DOUBLE_PRECISION,
. 0, MPI_COMM_WORLD, err)
enddo
endif
else
c read the reference ion from the master process
call MPI_Bcast(ref_ion, 3, MPI_DOUBLE_PRECISION,
. 0, MPI_COMM_WORLD, err)
c read the array of ions from the master process
call MPI_Bcast(n_ions, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, err)
do i=1,n_ions
call MPI_Bcast(ion, 3, MPI_DOUBLE_PRECISION,
. 0, MPI_COMM_WORLD, err)
ions_array(i,1) = ion(1)
ions_array(i,2) = ion(2)
ions_array(i,3) = ion(3)
enddo
endif
energy = 0
total_energy = 0
num_calc = n_ions / nprocs
start = rank*num_calc + 1;
stop = start + num_calc - 1;
if (rank .eq. nprocs-1) then
stop = n_ions
endif
do i=start,stop
energy = energy + calc_energy(ref_ion(1),
. ref_ion(2),
. ref_ion(3),
. ions_array(i, 1),
. ions_array(i, 2),
. ions_array(i, 3))
enddo
print *,"Process ",rank," (",start," to ",stop,
. ") Energy = ",energy
call MPI_Reduce(energy, total_energy, 1, MPI_DOUBLE_PRECISION,
. MPI_SUM, 0, MPI_COMM_WORLD, err)
if (rank .eq. 0) then
print *,"The total energy is ",total_energy
endif
call MPI_Finalize(err)
end
The new MPI function here is MPI_Bcast(void message, integer size, MPI_INTEGER, integer process, MPI_COMM_WORLD, err)
. This function copies the message held in message
on the process whose rank is in process
and broadcasts it so that it is received into message
by all of the other processes in the MPI process team. MPI_Bcast
is very useful when you want to send the same message to all processes in a team.
Compile the example using;
mpif77 mapreduce.f -o mapreduce
This will give you an executable called mapreduce
.