diff --git a/examples/heatTransfer/read/ReadSettings.cpp b/examples/heatTransfer/read/ReadSettings.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..96902ecf904d599041db1e9f916aa2930acb065e
--- /dev/null
+++ b/examples/heatTransfer/read/ReadSettings.cpp
@@ -0,0 +1,83 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * Settings.cpp
+ *
+ *  Created on: Dec 2017
+ *      Author: Norbert Podhorszki
+ */
+
+#include "ReadSettings.h"
+
+#include <cstdlib>
+#include <errno.h>
+#include <iomanip>
+#include <iostream>
+#include <stdexcept>
+
+static unsigned int convertToUint(std::string varName, char *arg)
+{
+    char *end;
+    int retval = std::strtoll(arg, &end, 10);
+    if (end[0] || errno == ERANGE)
+    {
+        throw std::invalid_argument("Invalid value given for " + varName +
+                                    ": " + std::string(arg));
+    }
+    if (retval < 0)
+    {
+        throw std::invalid_argument("Negative value given for " + varName +
+                                    ": " + std::string(arg));
+    }
+    return (unsigned int)retval;
+}
+
+ReadSettings::ReadSettings(int argc, char *argv[], int rank, int nproc)
+: rank{rank}
+{
+    if (argc < 5)
+    {
+        throw std::invalid_argument("Not enough arguments");
+    }
+    this->nproc = (unsigned int)nproc;
+
+    configfile = argv[1];
+    inputfile = argv[2];
+    npx = convertToUint("N", argv[3]);
+    npy = convertToUint("M", argv[4]);
+
+    if (npx * npy != this->nproc)
+    {
+        throw std::invalid_argument("N*M must equal the number of processes");
+    }
+    posx = rank % npx;
+    posy = rank / npx;
+}
+
+void ReadSettings::DecomposeArray(int gndx, int gndy)
+{
+    // 2D decomposition of global array reading
+    size_t ndx = gndx / npx;
+    size_t ndy = gndy / npy;
+    size_t offsx = ndx * posx;
+    size_t offsy = ndy * posy;
+    if (posx == npx - 1)
+    {
+        // right-most processes need to read all the rest of columns
+        ndx = gndy - ndx * (npx - 1);
+    }
+
+    if (posy == npy - 1)
+    {
+        // bottom processes need to read all the rest of rows
+        ndy = gndy - ndy * (npy - 1);
+    }
+    readsize.push_back(ndx);
+    readsize.push_back(ndy);
+    offset.push_back(offsx);
+    offset.push_back(offsy);
+
+    std::cout << "rank " << rank << " reads 2D slice " << ndx << " x " << ndy
+              << " from offset (" << offsx << "," << offsy << ")" << std::endl;
+}
diff --git a/examples/heatTransfer/read/ReadSettings.h b/examples/heatTransfer/read/ReadSettings.h
new file mode 100644
index 0000000000000000000000000000000000000000..2389864a25ca23c743d496bb78ce82dce21a4c8e
--- /dev/null
+++ b/examples/heatTransfer/read/ReadSettings.h
@@ -0,0 +1,44 @@
+/*
+ * Distributed under the OSI-approved Apache License, Version 2.0.  See
+ * accompanying file Copyright.txt for details.
+ *
+ * Settings.h
+ *
+ *  Created on: Dec 2017
+ *      Author: Norbert Podhorszki
+ */
+
+#ifndef READSETTINGS_H_
+#define READSETTINGS_H_
+
+#include <string>
+#include <vector>
+
+class ReadSettings
+{
+
+public:
+    // user arguments
+    std::string configfile;
+    std::string inputfile;
+    unsigned int npx; // Number of processes in X (slow) dimension
+    unsigned int npy; // Number of processes in Y (fast) dimension
+
+    int rank;
+    int nproc;
+
+    // Calculated in constructor
+    unsigned int posx; // Position of this process in X dimension
+    unsigned int posy; // Position of this process in Y dimension
+
+    // Calculated in DecomposeArray
+    std::vector<size_t>
+        readsize; // Local array size in X-Y dimensions per process
+    std::vector<size_t>
+        offset; // Offset of local array in X-Y dimensions on this process
+
+    ReadSettings(int argc, char *argv[], int rank, int nproc);
+    void DecomposeArray(int gndx, int gndy);
+};
+
+#endif /* READSETTINGS_H_ */