diff --git a/post-process.py b/post-process.py
new file mode 100755
index 0000000000000000000000000000000000000000..746db3503a9c1f6db7196595c7b4796a99100379
--- /dev/null
+++ b/post-process.py
@@ -0,0 +1,111 @@
+#!/usr/bin/env python
+"""
+Usage:
+    post-process.py [options] output-log
+
+Match the sends and recvs across the ranks and output a unified log.
+
+This file is part of SWIFT.
+
+Copyright (C) 2019 Peter W. Draper (p.w.draper@durham.ac.uk)
+All Rights Reserved.
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published
+by the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+"""
+
+import sys
+import argparse
+
+#  Handle the command line.
+parser = argparse.ArgumentParser(description="Match MPI reports")
+
+parser.add_argument(
+    "input",
+    help="Output log from simulator")
+parser.add_argument(
+    "-v",
+    "--verbose",
+    dest="verbose",
+    help="Verbose output",
+    default=False,
+    action="store_true",
+)
+args = parser.parse_args()
+infile = args.input
+
+#  Indices for words in a line.
+logticcol=0
+logcol=1
+injcol=2
+endcol=3
+dticcol=4
+stepcol=5
+rankcol=6
+otherrankcol=7
+itypecol=8
+isubtypecol=9
+tagcol=10
+sizecol=11
+ntestcol=12
+sumcol=13
+mincol=14
+maxcol=15
+
+#  Keyed lines.
+sends = {}
+recvs = {}
+
+#  Gather keys from the input log. We created dicts with matchable keys
+#  for when sends start and recvs end. Other pairings are possible...
+#  Note size of completion recv is negative.
+with open(infile, "r") as fp:
+    for line in fp:
+        if line[0] == '#':
+            continue
+        words = line.split()
+        if words[itypecol] == "22":
+            key = words[otherrankcol] + "/" + \
+                  words[rankcol] + "/" + \
+                  words[isubtypecol] + "/" + \
+                  words[tagcol] + "/" + \
+                  words[sizecol]
+            if not key in sends:
+                sends[key] = [line[:-1]]
+            else:
+                sends[key].append(line[:-1])
+
+        elif words[itypecol] == "23":
+            key = words[rankcol] + "/" + \
+                  words[otherrankcol] + "/" + \
+                  words[isubtypecol] + "/" + \
+                  words[tagcol] + "/" + \
+                  words[sizecol]
+            if not key in recvs:
+                recvs[key] = [line[:-1]]
+            else:
+                recvs[key].append(line[:-1])
+
+#  Now output. Note we could have unmatched recv keys, we don't check for that.
+print "# send_logticin send_logtic send_injtic send_endtic send_dtic send_step send_rank send_otherrank send_itype send_isubtype send_tag send_size send_nr_tests send_tsum send_tmin send_tmax recv_logticin recv_logtic recv_injtic recv_endtic recv_dtic recv_step recv_rank recv_otherrank recv_itype recv_isubtype recv_tag recv_size recv_nr_tests recv_tsum recv_tmin recv_tmax"
+for key in sends:
+    if key in recvs:
+        if len(sends[key]) == 1 and len(recvs[key]) == 1:
+            print sends[key][0], recvs[key][0]
+        else:
+            print "# ERROR: found ", len(sends[key]), "/", len(recvs[key]), " matches for key: ", key, " should be 1/1"
+    else:
+        print "# ERROR: missing recv key: ", key
+
+
+sys.exit(0)