diff --git a/src/fileFormats/vtk/read/vtkUnstructuredReader.C b/src/fileFormats/vtk/read/vtkUnstructuredReader.C
index 73e5a839cfa5f35bc6ed19e54220f9e9d0e744bb..60d47b512a46c87d3b1b0263c7a8989761e82aa5 100644
--- a/src/fileFormats/vtk/read/vtkUnstructuredReader.C
+++ b/src/fileFormats/vtk/read/vtkUnstructuredReader.C
@@ -33,6 +33,7 @@ License
 #include "cellModel.H"
 #include "vectorIOField.H"
 #include "triPointRef.H"
+#include "stringOps.H"
 
 /* * * * * * * * * * * * * * * Static Member Data  * * * * * * * * * * * * * */
 
@@ -48,6 +49,7 @@ const Foam::Enum
 Foam::vtkUnstructuredReader::vtkDataTypeNames
 ({
     { vtkDataType::VTK_INT, "int" },
+    // Not yet required: { vtkDataType::VTK_INT64, "vtktypeint64" },
     { vtkDataType::VTK_UINT, "unsigned_int" },
     { vtkDataType::VTK_LONG, "long" },
     { vtkDataType::VTK_ULONG, "unsigned_long" },
@@ -84,28 +86,87 @@ Foam::vtkUnstructuredReader::parseModeNames
 });
 
 
-// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
+// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+// Read N elements into List
+template<class T>
+static inline void readBlock(Istream& is, const label n, List<T>& list)
+{
+    list.resize(n);
+    for (T& val : list)
+    {
+        is >> val;
+    }
+}
+
+} // End namespace Foam
+
+
+// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
 
 void Foam::vtkUnstructuredReader::warnUnhandledType
 (
-    Istream& inFile,
+    const Istream& is,
     const label type,
     labelHashSet& warningGiven
-) const
+)
 {
     if (warningGiven.insert(type))
     {
-        IOWarningInFunction(inFile)
+        IOWarningInFunction(is)
             << "Skipping unknown cell type " << type << nl;
     }
 }
 
 
+// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
+
+void Foam::vtkUnstructuredReader::readOffsetsConnectivity
+(
+    ISstream& is,
+    const char* entryName,
+    const label nOffsets,
+    labelList& offsets,
+    const label nConnectivity,
+    labelList& connectivity
+)
+{
+    token tok;
+
+    is.read(tok);
+    if (!tok.isWord("OFFSETS"))
+    {
+        FatalIOErrorInFunction(is)
+            << "Expected OFFSETS for " << entryName
+            << ", found "
+            << tok.info() << nl
+            << exit(FatalIOError);
+    }
+    is.getLine(nullptr);  // Consume rest of line
+    readBlock(is, nOffsets, offsets);
+
+    is.read(tok);
+    if (!tok.isWord("CONNECTIVITY"))
+    {
+        FatalIOErrorInFunction(is)
+            << "Expected CONNECTIVITY for " << entryName
+            << ", found " << tok.info() << nl
+            << exit(FatalIOError);
+    }
+    is.getLine(nullptr);  // Consume rest of line
+    readBlock(is, nConnectivity, connectivity);
+}
+
+
 void Foam::vtkUnstructuredReader::extractCells
 (
-    Istream& inFile,
-    const labelList& cellTypes,
-    const labelList& cellVertData
+    const Istream& is,
+    const labelUList& cellTypes,
+    const labelUList& elemOffsets,
+    const labelUList& elemVerts
 )
 {
     const cellModel& hex = cellModel::ref(cellModel::HEX);
@@ -113,233 +174,258 @@ void Foam::vtkUnstructuredReader::extractCells
     const cellModel& pyr = cellModel::ref(cellModel::PYR);
     const cellModel& tet = cellModel::ref(cellModel::TET);
 
-    labelList tetPoints(4);
-    labelList pyrPoints(5);
-    labelList prismPoints(6);
-    labelList hexPoints(8);
+    // Pass 0: sizing
+    label nCells = 0, nFaces = 0, nLines = 0;
+    forAll(cellTypes, elemi)
+    {
+        switch (cellTypes[elemi])
+        {
+            case vtk::cellType::VTK_LINE:
+            case vtk::cellType::VTK_POLY_LINE:
+            {
+                ++nLines;
+            }
+            break;
+
+            case vtk::cellType::VTK_TRIANGLE:
+            case vtk::cellType::VTK_QUAD:
+            case vtk::cellType::VTK_POLYGON:
+            {
+                ++nFaces;
+            }
+            break;
+
+            case vtk::cellType::VTK_TETRA:
+            case vtk::cellType::VTK_PYRAMID:
+            case vtk::cellType::VTK_WEDGE:
+            case vtk::cellType::VTK_HEXAHEDRON:
+            {
+                ++nCells;
+            }
+            break;
+
+            default:
+                break;
+        }
+    }
 
     label celli = cells_.size();
-    cells_.setSize(celli+cellTypes.size());
-    cellMap_.setSize(cells_.size(), -1);
+    cells_.resize(celli + nCells);
+    cellMap_.resize(cells_.size(), -1);
 
     label facei = faces_.size();
-    faces_.setSize(facei+cellTypes.size());
-    faceMap_.setSize(faces_.size(), -1);
+    faces_.resize(facei + nFaces);
+    faceMap_.resize(faces_.size(), -1);
 
-    label lineI = lines_.size();
-    lines_.setSize(lineI+cellTypes.size());
-    lineMap_.setSize(lines_.size(), -1);
+    label linei = lines_.size();
+    lines_.resize(linei + nLines);
+    lineMap_.resize(lines_.size(), -1);
 
-    label dataIndex = 0;
+    // General scratch space for cell vertices
+    labelList cellPoints(16);
 
+    label dataIndex = 0;  // Addressing into vertices stream
 
     // To mark whether unhandled type has been visited.
     labelHashSet warningGiven;
 
-    forAll(cellTypes, i)
+
+    forAll(cellTypes, elemi)
     {
-        switch (cellTypes[i])
+        // Vertices per element - from offsets or embedded size
+        const label nVerts =
+        (
+            elemOffsets.empty()
+          ? elemVerts[dataIndex++]
+          : (elemOffsets[elemi+1] - elemOffsets[elemi])
+        );
+
+        // The addresseed vertices
+        const labelSubList verts(elemVerts, nVerts, dataIndex);
+        dataIndex += nVerts;
+
+        switch (cellTypes[elemi])
         {
             case vtk::cellType::VTK_VERTEX:
             {
-                warnUnhandledType(inFile, cellTypes[i], warningGiven);
-                label nRead = cellVertData[dataIndex++];
-                if (nRead != 1)
+                warnUnhandledType(is, cellTypes[elemi], warningGiven);
+                if (nVerts != 1)
                 {
-                    FatalIOErrorInFunction(inFile)
-                        << "Expected size 1 for VTK_VERTEX but found "
-                        << nRead << exit(FatalIOError);
+                    FatalIOErrorInFunction(is)
+                        << "Expected size 1 for VTK_VERTEX, found "
+                        << nVerts << nl
+                        << exit(FatalIOError);
                 }
-                dataIndex += nRead;
             }
             break;
 
             case vtk::cellType::VTK_POLY_VERTEX:
             {
-                warnUnhandledType(inFile, cellTypes[i], warningGiven);
-                label nRead = cellVertData[dataIndex++];
-                dataIndex += nRead;
+                warnUnhandledType(is, cellTypes[elemi], warningGiven);
             }
             break;
 
             case vtk::cellType::VTK_LINE:
             {
-                //warnUnhandledType(inFile, cellTypes[i], warningGiven);
-                label nRead = cellVertData[dataIndex++];
-                if (nRead != 2)
+                if (nVerts != 2)
                 {
-                    FatalIOErrorInFunction(inFile)
-                        << "Expected size 2 for VTK_LINE but found "
-                        << nRead << exit(FatalIOError);
+                    FatalIOErrorInFunction(is)
+                        << "Expected size 2 for VTK_LINE, found "
+                        << nVerts << nl
+                        << exit(FatalIOError);
                 }
-                lineMap_[lineI] = i;
-                labelList& segment = lines_[lineI++];
-                segment.setSize(2);
-                segment[0] = cellVertData[dataIndex++];
-                segment[1] = cellVertData[dataIndex++];
+                lineMap_[linei] = elemi;
+
+                // Same vertex ordering
+                lines_[linei++] = verts;
             }
             break;
 
             case vtk::cellType::VTK_POLY_LINE:
             {
-                //warnUnhandledType(inFile, cellTypes[i], warningGiven);
-                label nRead = cellVertData[dataIndex++];
-                lineMap_[lineI] = i;
-                labelList& segment = lines_[lineI++];
-                segment.setSize(nRead);
-                for (label& pointi : segment)
-                {
-                    pointi = cellVertData[dataIndex++];
-                }
+                lineMap_[linei] = elemi;
+
+                // Same vertex ordering
+                lines_[linei++] = verts;
             }
             break;
 
             case vtk::cellType::VTK_TRIANGLE:
             {
-                faceMap_[facei] = i;
-                face& f = faces_[facei++];
-                f.setSize(3);
-                label nRead = cellVertData[dataIndex++];
-                if (nRead != 3)
+                if (nVerts != 3)
                 {
-                    FatalIOErrorInFunction(inFile)
-                        << "Expected size 3 for VTK_TRIANGLE but found "
-                        << nRead << exit(FatalIOError);
+                    FatalIOErrorInFunction(is)
+                        << "Expected size 3 for VTK_TRIANGLE, found "
+                        << nVerts << nl
+                        << exit(FatalIOError);
                 }
-                f[0] = cellVertData[dataIndex++];
-                f[1] = cellVertData[dataIndex++];
-                f[2] = cellVertData[dataIndex++];
+                faceMap_[facei] = elemi;
+
+                // Same vertex ordering
+                static_cast<labelList&>(faces_[facei++]) = verts;
             }
             break;
 
             case vtk::cellType::VTK_QUAD:
             {
-                faceMap_[facei] = i;
-                face& f = faces_[facei++];
-                f.setSize(4);
-                label nRead = cellVertData[dataIndex++];
-                if (nRead != 4)
+                if (nVerts != 4)
                 {
-                    FatalIOErrorInFunction(inFile)
-                        << "Expected size 4 for VTK_QUAD but found "
-                        << nRead << exit(FatalIOError);
+                    FatalIOErrorInFunction(is)
+                        << "Expected size 4 for VTK_QUAD, found "
+                        << nVerts << nl
+                        << exit(FatalIOError);
                 }
-                f[0] = cellVertData[dataIndex++];
-                f[1] = cellVertData[dataIndex++];
-                f[2] = cellVertData[dataIndex++];
-                f[3] = cellVertData[dataIndex++];
+                faceMap_[facei] = elemi;
+
+                // Same vertex ordering
+                static_cast<labelList&>(faces_[facei++]) = verts;
             }
             break;
 
             case vtk::cellType::VTK_POLYGON:
             {
-                faceMap_[facei] = i;
-                face& f = faces_[facei++];
-                label nRead = cellVertData[dataIndex++];
-                f.setSize(nRead);
-                for (label& pointi : f)
-                {
-                    pointi = cellVertData[dataIndex++];
-                }
+                faceMap_[facei] = elemi;
+
+                // Same vertex ordering
+                static_cast<labelList&>(faces_[facei++]) = verts;
             }
             break;
 
             case vtk::cellType::VTK_TETRA:
             {
-                label nRead = cellVertData[dataIndex++];
-                if (nRead != 4)
+                if (nVerts != 4)
                 {
-                    FatalIOErrorInFunction(inFile)
-                        << "Expected size 4 for VTK_TETRA but found "
-                        << nRead << exit(FatalIOError);
+                    FatalIOErrorInFunction(is)
+                        << "Expected size 4 for VTK_TETRA, found "
+                        << nVerts << nl
+                        << exit(FatalIOError);
                 }
-                tetPoints[0] = cellVertData[dataIndex++];
-                tetPoints[1] = cellVertData[dataIndex++];
-                tetPoints[2] = cellVertData[dataIndex++];
-                tetPoints[3] = cellVertData[dataIndex++];
-                cellMap_[celli] = i;
-                cells_[celli++] = cellShape(tet, tetPoints, true);
+                cellMap_[celli] = elemi;
+
+                // Same vertex ordering
+                cells_[celli++].reset(tet, verts, true);
             }
             break;
 
             case vtk::cellType::VTK_PYRAMID:
             {
-                label nRead = cellVertData[dataIndex++];
-                if (nRead != 5)
+                if (nVerts != 5)
                 {
-                    FatalIOErrorInFunction(inFile)
-                        << "Expected size 5 for VTK_PYRAMID but found "
-                        << nRead << exit(FatalIOError);
+                    FatalIOErrorInFunction(is)
+                        << "Expected size 5 for VTK_PYRAMID, found "
+                        << nVerts << nl
+                        << exit(FatalIOError);
                 }
-                pyrPoints[0] = cellVertData[dataIndex++];
-                pyrPoints[1] = cellVertData[dataIndex++];
-                pyrPoints[2] = cellVertData[dataIndex++];
-                pyrPoints[3] = cellVertData[dataIndex++];
-                pyrPoints[4] = cellVertData[dataIndex++];
-                cellMap_[celli] = i;
-                cells_[celli++] = cellShape(pyr, pyrPoints, true);
+                cellMap_[celli] = elemi;
+
+                // Same vertex ordering
+                cells_[celli++].reset(pyr, verts, true);
             }
             break;
 
             case vtk::cellType::VTK_WEDGE:
             {
-                label nRead = cellVertData[dataIndex++];
-                if (nRead != 6)
+                if (nVerts != 6)
                 {
-                    FatalIOErrorInFunction(inFile)
-                        << "Expected size 6 for VTK_WEDGE but found "
-                        << nRead << exit(FatalIOError);
+                    FatalIOErrorInFunction(is)
+                        << "Expected size 6 for VTK_WEDGE, found "
+                        << nVerts << nl
+                        << exit(FatalIOError);
                 }
-                //- From mesh description in vtk documentation
-                prismPoints[0] = cellVertData[dataIndex++];
-                prismPoints[2] = cellVertData[dataIndex++];
-                prismPoints[1] = cellVertData[dataIndex++];
-                prismPoints[3] = cellVertData[dataIndex++];
-                prismPoints[5] = cellVertData[dataIndex++];
-                prismPoints[4] = cellVertData[dataIndex++];
-                cellMap_[celli] = i;
-                cells_[celli++] = cellShape(prism, prismPoints, true);
+                cellMap_[celli] = elemi;
+
+                // VTK_WEDGE triangles point outwards (swap 1<->2, 4<->5)
+                labelSubList shape(cellPoints, nVerts);
+                shape[0] = verts[0];
+                shape[2] = verts[1];
+                shape[1] = verts[2];
+                shape[3] = verts[3];
+                shape[5] = verts[4];
+                shape[4] = verts[5];
+
+                cells_[celli++].reset(prism, shape, true);
             }
             break;
 
             case vtk::cellType::VTK_HEXAHEDRON:
             {
-                label nRead = cellVertData[dataIndex++];
-                if (nRead != 8)
+                if (nVerts != 8)
                 {
-                    FatalIOErrorInFunction(inFile)
-                        << "Expected size 8 for VTK_HEXAHEDRON but found "
-                        << nRead << exit(FatalIOError);
+                    FatalIOErrorInFunction(is)
+                        << "Expected size 8 for VTK_HEXAHEDRON, found "
+                        << nVerts << nl
+                        << exit(FatalIOError);
                 }
-                hexPoints[0] = cellVertData[dataIndex++];
-                hexPoints[1] = cellVertData[dataIndex++];
-                hexPoints[2] = cellVertData[dataIndex++];
-                hexPoints[3] = cellVertData[dataIndex++];
-                hexPoints[4] = cellVertData[dataIndex++];
-                hexPoints[5] = cellVertData[dataIndex++];
-                hexPoints[6] = cellVertData[dataIndex++];
-                hexPoints[7] = cellVertData[dataIndex++];
-                cellMap_[celli] = i;
-                cells_[celli++] = cellShape(hex, hexPoints, true);
+                cellMap_[celli] = elemi;
+
+                // Same vertex ordering
+                cells_[celli++].reset(hex, verts, true);
             }
             break;
 
             default:
-                warnUnhandledType(inFile, cellTypes[i], warningGiven);
-                label nRead = cellVertData[dataIndex++];
-                dataIndex += nRead;
+            {
+                warnUnhandledType(is, cellTypes[elemi], warningGiven);
+            }
+            break;
         }
     }
 
     DebugInfo
-        << "Read " << celli << " cells;" << facei << " faces." << nl;
-
-    cells_.setSize(celli);
-    cellMap_.setSize(celli);
-    faces_.setSize(facei);
-    faceMap_.setSize(facei);
-    lines_.setSize(lineI);
-    lineMap_.setSize(lineI);
+        << "Read"
+        << " cells:" << celli
+        << " faces:" << facei
+        << " lines:" << linei
+        << nl;
+
+    cells_.resize(celli);
+    cellMap_.resize(celli);
+
+    faces_.resize(facei);
+    faceMap_.resize(facei);
+
+    lines_.resize(linei);
+    lineMap_.resize(linei);
 }
 
 
@@ -357,6 +443,7 @@ void Foam::vtkUnstructuredReader::readField
         switch (vtkDataTypeNames[dataType])
         {
             case VTK_INT:
+            case VTK_INT64:
             case VTK_UINT:
             case VTK_LONG:
             case VTK_ULONG:
@@ -465,7 +552,8 @@ Foam::wordList Foam::vtkUnstructuredReader::readFieldArray
         {
             FatalIOErrorInFunction(inFile)
                 << "Expected " << wantedSize << " tuples but only have "
-                << numTuples << exit(FatalIOError);
+                << numTuples << nl
+                << exit(FatalIOError);
         }
 
         readField
@@ -505,14 +593,15 @@ Foam::objectRegistry& Foam::vtkUnstructuredReader::selectRegistry
 Foam::vtkUnstructuredReader::vtkUnstructuredReader
 (
     const objectRegistry& obr,
-    ISstream& inFile
+    ISstream& is
 )
 :
+    version_(2.0),
     cellData_(IOobject("cellData", obr)),
     pointData_(IOobject("pointData", obr)),
     otherData_(IOobject("otherData", obr))
 {
-    read(inFile);
+    read(is);
 }
 
 
@@ -521,6 +610,18 @@ void Foam::vtkUnstructuredReader::read(ISstream& inFile)
     inFile.getLine(header_);
     DebugInfo<< "Header   : " << header_ << nl;
 
+    // Extract version number from "# vtk DataFile Version 5.1"
+    const auto split = stringOps::splitSpace(header_);
+    if (split.size() >= 4 && split[split.size() - 2] == "Version")
+    {
+        float ver(0);
+        if (readFloat(split[split.size() - 1], ver))
+        {
+            version_ = ver;
+            DebugInfo<< "Version  : " << version_ << nl;
+        }
+    }
+
     inFile.getLine(title_);
     DebugInfo<< "Title    : " << title_ << nl;
 
@@ -530,7 +631,7 @@ void Foam::vtkUnstructuredReader::read(ISstream& inFile)
     if (dataType_ == "BINARY")
     {
         FatalIOErrorInFunction(inFile)
-            << "Binary reading not supported"
+            << "Binary reading not supported" << nl
             << exit(FatalIOError);
     }
 
@@ -538,8 +639,8 @@ void Foam::vtkUnstructuredReader::read(ISstream& inFile)
     label wantedSize = -1;
 
 
-    // Temporary storage for vertices of cells.
-    labelList cellVerts;
+    // Intermediate storage for vertices of cells.
+    labelList cellOffsets, cellVerts;
 
     token tok;
 
@@ -561,19 +662,18 @@ void Foam::vtkUnstructuredReader::read(ISstream& inFile)
         }
         else if (tag == "POINTS")
         {
-            label nPoints(readLabel(inFile));
-            points_.setSize(nPoints);    ///3);
+            const label nPoints(readLabel(inFile));
+            points_.resize(nPoints);
 
             DebugInfo
-                << "Reading " << nPoints << " numbers representing "
-                << points_.size() << " coordinates." << nl;
+                << "Reading " << nPoints << " coordinates" << nl;
 
             word primitiveTag(inFile);
             if (primitiveTag != "float" && primitiveTag != "double")
             {
                 FatalIOErrorInFunction(inFile)
-                    << "Expected 'float' entry but found "
-                    << primitiveTag
+                    << "Expected 'float' entry, found "
+                    << primitiveTag << nl
                     << exit(FatalIOError);
             }
             for (point& p : points_)
@@ -584,84 +684,169 @@ void Foam::vtkUnstructuredReader::read(ISstream& inFile)
         else if (tag == "CELLS")
         {
             label nCells(readLabel(inFile));
-            label nNumbers(readLabel(inFile));
-            DebugInfo
-                << "Reading " << nCells << " cells or faces." << nl;
+            const label nNumbers(readLabel(inFile));
+
+            if (version_ < 5.0)
+            {
+                // VTK 4.2 and earlier (single-block)
+                DebugInfo
+                    << "Reading " << nCells
+                    << " cells/faces (single block)" << nl;
 
-            readBlock(inFile, nNumbers, cellVerts);
+                cellOffsets.clear();
+                readBlock(inFile, nNumbers, cellVerts);
+            }
+            else
+            {
+                // VTK 5.0 and later (OFFSETS and CONNECTIVITY)
+
+                const label nOffsets(nCells);
+                --nCells;
+
+                DebugInfo
+                    << "Reading offsets/connectivity for "
+                    << nCells << " cells/faces" << nl;
+
+                readOffsetsConnectivity
+                (
+                    inFile,
+                    "CELLS",
+                    nOffsets, cellOffsets,
+                    nNumbers, cellVerts
+                );
+            }
         }
         else if (tag == "CELL_TYPES")
         {
-            label nCellTypes(readLabel(inFile));
+            const label nCellTypes(readLabel(inFile));
 
             labelList cellTypes;
             readBlock(inFile, nCellTypes, cellTypes);
 
-            if (cellTypes.size() > 0 && cellVerts.size() == 0)
+            if (!cellTypes.empty() && cellVerts.empty())
             {
                 FatalIOErrorInFunction(inFile)
                     << "Found " << cellTypes.size()
-                    << " cellTypes but no cells."
+                    << " cellTypes but no cells." << nl
                     << exit(FatalIOError);
             }
 
-            extractCells(inFile, cellTypes, cellVerts);
+            extractCells(inFile, cellTypes, cellOffsets, cellVerts);
+            cellOffsets.clear();
             cellVerts.clear();
         }
         else if (tag == "LINES")
         {
             label nLines(readLabel(inFile));
-            label nNumbers(readLabel(inFile));
-            DebugInfo
-                << "Reading " << nLines << " lines." << nl;
+            const label nNumbers(readLabel(inFile));
+
+            labelList elemOffsets, elemVerts;
+
+            if (version_ < 5.0)
+            {
+                // VTK 4.2 and earlier (single-block)
+                DebugInfo
+                    << "Reading " << nLines
+                    << " lines (single block)" << nl;
+
+                readBlock(inFile, nNumbers, elemVerts);
+            }
+            else
+            {
+                // VTK 5.0 and later (OFFSETS and CONNECTIVITY)
 
-            labelList lineVerts;
-            readBlock(inFile, nNumbers, lineVerts);
+                const label nOffsets(nLines);
+                --nLines;
 
-            label lineI = lines_.size();
-            lines_.setSize(lineI+nLines);
-            lineMap_.setSize(lines_.size());
+                DebugInfo
+                    << "Reading offsets/connectivity for "
+                    << nLines << " lines" << nl;
 
-            label elemI = 0;
+                readOffsetsConnectivity
+                (
+                    inFile,
+                    "LINES",
+                    nOffsets, elemOffsets,
+                    nNumbers, elemVerts
+                );
+            }
+
+            // Append into lines
+            label linei = lines_.size();
+            lines_.resize(linei+nLines);
+            lineMap_.resize(lines_.size());
+
+            label dataIndex = 0;
             for (label i = 0; i < nLines; i++)
             {
-                lineMap_[lineI] = lineI;
-                labelList& f = lines_[lineI];
-                f.setSize(lineVerts[elemI++]);
-                for (label& pointi : f)
-                {
-                    pointi = lineVerts[elemI++];
-                }
-                lineI++;
+                const label nVerts =
+                (
+                    elemOffsets.empty()
+                  ? elemVerts[dataIndex++]
+                  : (elemOffsets[i+1] - elemOffsets[i])
+                );
+                const labelSubList verts(elemVerts, nVerts, dataIndex);
+                dataIndex += nVerts;
+
+                lineMap_[linei] = linei;
+                lines_[linei++] = verts;
             }
         }
         else if (tag == "POLYGONS")
         {
-            // If in polydata mode
-
             label nFaces(readLabel(inFile));
-            label nNumbers(readLabel(inFile));
-            DebugInfo
-                << "Reading " << nFaces << " faces." << nl;
+            const label nNumbers(readLabel(inFile));
+
+            labelList elemOffsets, elemVerts;
+
+            if (version_ < 5.0)
+            {
+                // VTK 4.2 and earlier (single-block)
+                DebugInfo
+                    << "Reading " << nFaces
+                    << " faces (single block)" << nl;
+
+                readBlock(inFile, nNumbers, elemVerts);
+            }
+            else
+            {
+                // VTK 5.0 and later (OFFSETS and CONNECTIVITY)
+
+                const label nOffsets(nFaces);
+                --nFaces;
 
-            labelList faceVerts;
-            readBlock(inFile, nNumbers, faceVerts);
+                DebugInfo
+                    << "Reading offsets/connectivity for "
+                    << nFaces << " faces" << nl;
 
+                readOffsetsConnectivity
+                (
+                    inFile,
+                    "POLYGONS",
+                    nOffsets, elemOffsets,
+                    nNumbers, elemVerts
+                );
+            }
+
+            // Append into faces
             label facei = faces_.size();
-            faces_.setSize(facei+nFaces);
-            faceMap_.setSize(faces_.size());
+            faces_.resize(facei+nFaces);
+            faceMap_.resize(faces_.size());
 
-            label elemI = 0;
-            for (label i = 0; i < nFaces; i++)
+            label dataIndex = 0;
+            for (label i = 0; i < nFaces; ++i)
             {
+                const label nVerts =
+                (
+                    elemOffsets.empty()
+                  ? elemVerts[dataIndex++]
+                  : (elemOffsets[i+1] - elemOffsets[i])
+                );
+                const labelSubList verts(elemVerts, nVerts, dataIndex);
+                dataIndex += nVerts;
+
                 faceMap_[facei] = facei;
-                face& f = faces_[facei];
-                f.setSize(faceVerts[elemI++]);
-                for (label& pointi : f)
-                {
-                    pointi = faceVerts[elemI++];
-                }
-                facei++;
+                static_cast<labelList&>(faces_[facei++]) = verts;
             }
         }
         else if (tag == "POINT_DATA")
@@ -675,7 +860,8 @@ void Foam::vtkUnstructuredReader::read(ISstream& inFile)
             {
                 FatalIOErrorInFunction(inFile)
                     << "Reading POINT_DATA : expected " << wantedSize
-                    << " but read " << nPoints << exit(FatalIOError);
+                    << " but read " << nPoints << nl
+                    << exit(FatalIOError);
             }
         }
         else if (tag == "CELL_DATA")
@@ -689,7 +875,8 @@ void Foam::vtkUnstructuredReader::read(ISstream& inFile)
                 FatalIOErrorInFunction(inFile)
                     << "Reading CELL_DATA : expected "
                     << wantedSize
-                    << " but read " << nCells << exit(FatalIOError);
+                    << " but read " << nCells << nl
+                    << exit(FatalIOError);
             }
         }
         else if (tag == "FIELD")
@@ -716,7 +903,7 @@ void Foam::vtkUnstructuredReader::read(ISstream& inFile)
             {
                 FatalIOErrorInFunction(inFile)
                     << "Expected tag LOOKUP_TABLE but read "
-                    << lookupTableTag
+                    << lookupTableTag << nl
                     << exit(FatalIOError);
             }
 
@@ -800,49 +987,103 @@ void Foam::vtkUnstructuredReader::read(ISstream& inFile)
         else if (tag == "TRIANGLE_STRIPS")
         {
             label nStrips(readLabel(inFile));
-            label nNumbers(readLabel(inFile));
-            DebugInfo
-                << "Reading " << nStrips << " triangle strips." << nl;
+            const label nNumbers(readLabel(inFile));
+
+            labelList elemOffsets, elemVerts;
 
-            labelList faceVerts;
-            readBlock(inFile, nNumbers, faceVerts);
+            // Total number of faces in strips
+            label nFaces = 0;
 
-            // Count number of triangles
-            label elemI = 0;
-            label nTris = 0;
-            for (label i = 0; i < nStrips; i++)
+            if (version_ < 5.0)
             {
-                label nVerts = faceVerts[elemI++];
-                nTris += nVerts-2;
-                elemI += nVerts;
+                // VTK 4.2 and earlier (single-block)
+                DebugInfo
+                    << "Reading " << nStrips
+                    << " strips (single block)" << nl;
+
+                readBlock(inFile, nNumbers, elemVerts);
+
+                // Count number of faces (triangles)
+                {
+                    label dataIndex = 0;
+                    for (label i = 0; i < nStrips; ++i)
+                    {
+                        const label nVerts = elemVerts[dataIndex++];
+                        nFaces += nVerts-2;
+                        dataIndex += nVerts;
+                    }
+                }
             }
+            else
+            {
+                // VTK 5.0 and later (OFFSETS and CONNECTIVITY)
+
+                const label nOffsets(nStrips);
+                --nStrips;
+
+                DebugInfo
+                    << "Reading offsets/connectivity for "
+                    << nStrips << " triangle strips." << nl;
 
+                readOffsetsConnectivity
+                (
+                    inFile,
+                    "TRIANGLE_STRIPS",
+                    nOffsets, elemOffsets,
+                    nNumbers, elemVerts
+                );
 
-            // Store
+                // Count number of faces (triangles)
+                for (label i = 0; i < nStrips; ++i)
+                {
+                    const label nVerts = (elemOffsets[i+1] - elemOffsets[i]);
+                    nFaces += nVerts-2;
+                }
+            }
+
+            // Append into faces
             label facei = faces_.size();
-            faces_.setSize(facei+nTris);
-            faceMap_.setSize(faces_.size());
-            elemI = 0;
-            for (label i = 0; i < nStrips; i++)
+            faces_.resize(facei+nFaces);
+            faceMap_.resize(faces_.size());
+
+            label dataIndex = 0;
+            for (label i = 0; i < nStrips; ++i)
             {
-                label nVerts = faceVerts[elemI++];
-                label nTris = nVerts-2;
+                const label nVerts =
+                (
+                    elemOffsets.empty()
+                  ? elemVerts[dataIndex++]
+                  : (elemOffsets[i+1] - elemOffsets[i])
+                );
+                const label nTris = nVerts-2;
 
-                // Read first triangle
-                faceMap_[facei] = facei;
-                face& f = faces_[facei++];
-                f.setSize(3);
-                f[0] = faceVerts[elemI++];
-                f[1] = faceVerts[elemI++];
-                f[2] = faceVerts[elemI++];
-                for (label triI = 1; triI < nTris; triI++)
+                // Advance before the first triangle
+                if (nTris > 0)
+                {
+                    dataIndex += 2;
+                }
+
+                for (label triI = 0; triI < nTris; ++triI)
                 {
                     faceMap_[facei] = facei;
                     face& f = faces_[facei++];
-                    f.setSize(3);
-                    f[0] = faceVerts[elemI-1];
-                    f[1] = faceVerts[elemI-2];
-                    f[2] = faceVerts[elemI++];
+
+                    f.resize(3);
+
+                    // NOTE: not clear if the orientation is correct
+                    if ((triI % 2) == 0)
+                    {
+                        // Even (eg, 0-1-2, 2-3-4)
+                        f[0] = elemVerts[dataIndex-2];
+                        f[1] = elemVerts[dataIndex-1];
+                    }
+                    else
+                    {
+                        // Odd (eg, 2-1-3, 4-3-5)
+                        f[0] = elemVerts[dataIndex-1];
+                        f[1] = elemVerts[dataIndex-2];
+                    }
+                    f[2] = elemVerts[dataIndex++];
                 }
             }
         }
@@ -853,25 +1094,26 @@ void Foam::vtkUnstructuredReader::read(ISstream& inFile)
             {
                 FatalIOErrorInFunction(inFile)
                     << "Unsupported tag "
-                    << infoTag << exit(FatalIOError);
+                    << infoTag << nl
+                    << exit(FatalIOError);
             }
             label nInfo(readLabel(inFile));
             DebugInfo
-                << "Consuming " << nInfo << " metadata information." << nl;
+                << "Ignoring " << nInfo << " metadata information." << nl;
 
-            string line;
             // Consume rest of line
-            inFile.getLine(line);
+            inFile.getLine(nullptr);
             for (label i = 0; i < 2*nInfo; i++)
             {
-                inFile.getLine(line);
+                inFile.getLine(nullptr);
             }
         }
         else
         {
             FatalIOErrorInFunction(inFile)
                 << "Unsupported tag "
-                << tag << exit(FatalIOError);
+                << tag << nl
+                << exit(FatalIOError);
         }
     }
 
@@ -910,21 +1152,21 @@ void Foam::vtkUnstructuredReader::read(ISstream& inFile)
                     std::swap(shape[0], shape[3]);
                     std::swap(shape[1], shape[4]);
                     std::swap(shape[2], shape[5]);
-                    nSwapped++;
+                    ++nSwapped;
                 }
             }
         }
-        if (nSwapped > 0)
+        if (nSwapped)
         {
-            WarningInFunction << "Swapped " << nSwapped << " prismatic cells"
-                << nl;
+            WarningInFunction << "Swapped " << nSwapped
+                << " prismatic cells" << nl;
         }
     }
 
     if (debug)
     {
         Info<< "Read points:" << points_.size()
-            << " cellShapes:" << cells_.size()
+            << " cells:" << cells_.size()
             << " faces:" << faces_.size()
             << " lines:" << lines_.size()
             << nl << nl;
diff --git a/src/fileFormats/vtk/read/vtkUnstructuredReader.H b/src/fileFormats/vtk/read/vtkUnstructuredReader.H
index 6b06a630dd3bc04f6bffd3b230e940686aa3b47c..99bc48007842d326118619b1a48614ebfcf7cf3a 100644
--- a/src/fileFormats/vtk/read/vtkUnstructuredReader.H
+++ b/src/fileFormats/vtk/read/vtkUnstructuredReader.H
@@ -6,6 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2012-2016 OpenFOAM Foundation
+    Copyright (C) 2021 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -68,12 +69,13 @@ class vtkUnstructuredReader
 {
 public:
 
-    // Public data types
+    // Public Data Types
 
         //- Enumeration defining the vtk data types
         enum vtkDataType
         {
             VTK_INT,
+            VTK_INT64,
             VTK_UINT,
             VTK_LONG,
             VTK_ULONG,
@@ -112,6 +114,9 @@ public:
 
 private:
 
+    //- The VTK version
+    float version_;
+
     //- Header
     string header_;
 
@@ -160,27 +165,31 @@ private:
 
     // Private Member Functions
 
-        template<class T>
-        void readBlock
+        //- Read OFFSETS, CONNECTIVITY arrays
+        static void readOffsetsConnectivity
         (
-            Istream& inFile,
-            const label n,
-            List<T>& list
-        ) const;
+            ISstream& is,
+            const char* entryName,
+            const label nOffsets,
+            labelList& offsets,
+            const label nConnectivity,
+            labelList& connectivity
+        );
 
-        void warnUnhandledType
+        static void warnUnhandledType
         (
-            Istream& inFile,
+            const Istream& is,  // For error message
             const label type,
             labelHashSet& warningGiven
-        ) const;
+        );
 
         //- Split cellTypes into cells, faces and lines
         void extractCells
         (
-            Istream& inFile,
-            const labelList& cellTypes,
-            const labelList& cellVertData
+            const Istream& is,  // For error message
+            const labelUList& cellTypes,
+            const labelUList& cellOffsets,
+            const labelUList& cellVertData
         );
 
         //- Read single field and stores it on the objectRegistry.
@@ -215,121 +224,122 @@ public:
     //- Runtime type information
     ClassName("vtkUnstructuredReader");
 
+
     // Constructors
 
-        //- Construct from Istream, read all
-        vtkUnstructuredReader(const objectRegistry& obr, ISstream&);
+        //- Construct from input stream, read all
+        vtkUnstructuredReader(const objectRegistry& obr, ISstream& is);
 
 
     // Member Functions
 
         //- Header
-        const string header() const
+        const string& header() const noexcept
         {
             return header_;
         }
 
         //- Title
-        const string& title() const
+        const string& title() const noexcept
         {
             return title_;
         }
 
         //- DataType
-        const string& dataType() const
+        const string& dataType() const noexcept
         {
             return dataType_;
         }
 
 
         //- Points
-        const pointField& points() const
+        const pointField& points() const noexcept
         {
             return points_;
         }
 
-        pointField& points()
+        pointField& points() noexcept
         {
             return points_;
         }
 
-        //- 3D cells.
-        const cellShapeList& cells() const
+        //- 3D cells
+        const cellShapeList& cells() const noexcept
         {
             return cells_;
         }
 
-        cellShapeList& cells()
+        cellShapeList& cells() noexcept
         {
             return cells_;
         }
 
-        const labelList& cellMap() const
+        const labelList& cellMap() const noexcept
         {
             return cellMap_;
         }
 
         //- 2D cells (=faces)
-        const faceList& faces() const
+        const faceList& faces() const noexcept
         {
             return faces_;
         }
 
-        faceList& faces()
+        faceList& faces() noexcept
         {
             return faces_;
         }
 
-        const labelList& faceMap() const
+        const labelList& faceMap() const noexcept
         {
             return faceMap_;
         }
 
         //- 1D cells (=open lines)
-        const labelListList& lines() const
+        const labelListList& lines() const noexcept
         {
             return lines_;
         }
 
-        labelListList& lines()
+        labelListList& lines() noexcept
         {
             return lines_;
         }
 
-        const labelList& lineMap() const
+        const labelList& lineMap() const noexcept
         {
             return lineMap_;
         }
 
         //- Cell based fields
-        const objectRegistry& cellData() const
+        const objectRegistry& cellData() const noexcept
         {
             return cellData_;
         }
 
-        objectRegistry& cellData()
+        objectRegistry& cellData() noexcept
         {
             return cellData_;
         }
 
         //- Point based fields
-        const objectRegistry& pointData() const
+        const objectRegistry& pointData() const noexcept
         {
             return pointData_;
         }
 
-        objectRegistry& pointData()
+        objectRegistry& pointData() noexcept
         {
             return pointData_;
         }
 
         //- Other fields
-        const objectRegistry& otherData() const
+        const objectRegistry& otherData() const noexcept
         {
             return otherData_;
         }
 
-        objectRegistry& otherData()
+        objectRegistry& otherData() noexcept
         {
             return otherData_;
         }
@@ -337,8 +347,7 @@ public:
 
         //- Debug: print contents of objectRegistry
         template<class Type>
-        void printFieldStats(const objectRegistry&) const;
-
+        static void printFieldStats(const objectRegistry&);
 };
 
 
diff --git a/src/fileFormats/vtk/read/vtkUnstructuredReaderTemplates.C b/src/fileFormats/vtk/read/vtkUnstructuredReaderTemplates.C
index bd0bb80285633a505f0b90232b9e783128a81b08..b35ae66beb95cd96ca8e5ef9824e3ab0998994b5 100644
--- a/src/fileFormats/vtk/read/vtkUnstructuredReaderTemplates.C
+++ b/src/fileFormats/vtk/read/vtkUnstructuredReaderTemplates.C
@@ -6,6 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2012 OpenFOAM Foundation
+    Copyright (C) 2021 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -26,50 +27,26 @@ License
 \*---------------------------------------------------------------------------*/
 
 #include "vtkUnstructuredReader.H"
-#include "labelIOField.H"
-#include "scalarIOField.H"
-#include "stringIOList.H"
-#include "cellModel.H"
-#include "vectorIOField.H"
-
-// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
-
-template<class T>
-void Foam::vtkUnstructuredReader::readBlock
-(
-    Istream& inFile,
-    const label n,
-    List<T>& list
-) const
-{
-    list.setSize(n);
-    for (T& val : list)
-    {
-        inFile >> val;
-    }
-}
 
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
 template<class Type>
-void Foam::vtkUnstructuredReader::printFieldStats
-(
-    const objectRegistry& obj
-) const
+void Foam::vtkUnstructuredReader::printFieldStats(const objectRegistry& obj)
 {
-    wordList fieldNames(obj.names(Type::typeName));
+    const wordList fieldNames(obj.names(Type::typeName));
 
     if (fieldNames.size())
     {
-        Info<< "Read " << fieldNames.size() << " " << Type::typeName
+        Info<< "Read " << fieldNames.size() << ' ' << Type::typeName
             << " fields:" << nl
             << "Size\tName" << nl
-            << "----\t----" << endl;
+            << "----\t----" << nl;
 
         for (const word& fieldName : fieldNames)
         {
             Info<< obj.lookupObject<Type>(fieldName).size()
-                << "\t" << fieldName
-                << endl;
+                << '\t' << fieldName
+                << nl;
         }
         Info<< endl;
     }
diff --git a/src/surfMesh/surfaceFormats/vtk/VTKsurfaceFormat.C b/src/surfMesh/surfaceFormats/vtk/VTKsurfaceFormat.C
index 38f19dc70e81b64ca0168a6df062a1ab99ff101c..c1dcdf2fb575aa43696b9bf26a1fce86074c4c82 100644
--- a/src/surfMesh/surfaceFormats/vtk/VTKsurfaceFormat.C
+++ b/src/surfMesh/surfaceFormats/vtk/VTKsurfaceFormat.C
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2016 OpenFOAM Foundation
-    Copyright (C) 2016-2020 OpenCFD Ltd.
+    Copyright (C) 2016-2021 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -28,6 +28,7 @@ License
 
 #include "VTKsurfaceFormat.H"
 #include "vtkUnstructuredReader.H"
+#include "labelIOField.H"
 #include "scalarIOField.H"
 #include "faceTraits.H"
 #include <fstream>
@@ -222,7 +223,7 @@ bool Foam::fileFormats::VTKsurfaceFormat<Face>::read
 
         // Count
         labelList zoneSizes(nZones, Zero);
-        for (const label zonei : zones)
+        for (const label zonei : dynZones)
         {
             zoneSizes[zonei]++;
         }