diff --git a/L21/mpi_reduce.c b/L21/mpi_reduce.c
new file mode 100644
index 0000000000000000000000000000000000000000..23865fcb866b1a81d7549e5aeb9bf7ce8797a2f9
--- /dev/null
+++ b/L21/mpi_reduce.c
@@ -0,0 +1,58 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <mpi.h>
+
+int main(int argc, char *argv[]) {
+
+    MPI_Init (&argc, &argv);
+
+    // MPI_COMM_WORLD is the default communicator that contains all ranks
+    int rank, size;
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+    MPI_Comm_size(MPI_COMM_WORLD, &size);
+    char node_name[MPI_MAX_PROCESSOR_NAME];
+    int node_name_len;
+    MPI_Get_processor_name(node_name,&node_name_len);
+
+    // make sure we are not running on a login node!
+    if ((strcmp(node_name,"tinkercliffs1") == 0) || 
+            (strcmp(node_name,"tinkercliffs2") == 0)) {
+        printf ("error : running on login node %s!\n",node_name);
+        return 1;
+    }
+
+    // get the number of rounds from command line
+    if (argc < 3) {
+        printf ("Command usage : %s %s\n",argv[0],"rounds","seed");
+        return 1;
+    }
+    int rounds = atoi(argv[1]);
+    int seed = atoi(argv[2]);
+    srandom(seed+rank);
+
+    // start the timer
+    double start_time, end_time;
+    start_time = MPI_Wtime();
+
+    // random sum
+    int total_sum = 0;
+
+    for (int round = 0;round < rounds;round++) {
+	int round_sum = random() % 5;
+	int number = round_sum;
+	MPI_Reduce(&number,&round_sum,1,MPI_INT,MPI_SUM,0,MPI_COMM_WORLD);
+	total_sum += round_sum;
+    }
+
+    // stop the timer
+    end_time = MPI_Wtime();
+
+    // print results
+    if (rank == 0) {
+        printf ("elapsed time = %.4f seconds\n",end_time-start_time);
+	printf ("rounds = %d, seed = %d, sum = %d\n",rounds,seed,total_sum);
+    }
+
+    MPI_Finalize();
+}
diff --git a/L21/mpi_reduce.sh b/L21/mpi_reduce.sh
new file mode 100644
index 0000000000000000000000000000000000000000..64892b04e2425b702a9d3ec45f27a0eac355f0b1
--- /dev/null
+++ b/L21/mpi_reduce.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+#SBATCH -A cmda3634_rjh
+#SBATCH -p normal_q
+#SBATCH -t 5
+#SBATCH --nodes=64
+#SBATCH --ntasks-per-node=1
+#SBATCH -o mpi_reduce.out
+
+# Go to the directory where the job was submitted
+cd $SLURM_SUBMIT_DIR
+
+# Load the modules we need for MPI
+module load matplotlib
+
+# Build the executable
+mpicc -o mpi_reduce mpi_reduce.c
+
+# Run mpi_reduce
+mpiexec -n $SLURM_NTASKS --map-by ppr:$SLURM_NTASKS_PER_NODE:node ./mpi_reduce $1 $2
+
diff --git a/L21/mpi_reduce_64_1.out b/L21/mpi_reduce_64_1.out
new file mode 100644
index 0000000000000000000000000000000000000000..c3d40c6cd7a77c06f4fd1afa1222bf79f29aae64
--- /dev/null
+++ b/L21/mpi_reduce_64_1.out
@@ -0,0 +1,7 @@
+[jasonwil@tinkercliffs2 L21]$ sbatch mpi_reduce.sh 500000 1234
+[jasonwil@tinkercliffs2 L21]$ squeue -u jasonwil
+             JOBID PARTITION     NAME     USER ST       TIME  NODES NODELIST(REASON)
+           2300544  normal_q mpi_redu jasonwil  R       0:02     64 tc[003-004,006,009-010,012-013,015-016,018,020,022,024-027,032,035,037,046,049-053,056,059,061,066-067,070-071,075,079-087,089-090,095,099-101,104,133-134,179-181,196-201,239-240,253-254]
+[jasonwil@tinkercliffs2 L21]$ cat mpi_reduce.out
+elapsed time = 1.1595 seconds
+rounds = 500000, seed = 1234, sum = 64020814
\ No newline at end of file