diff --git a/applications/utilities/postProcessing/dataConversion/foamToVTK/convertProcessorPatches.H b/applications/utilities/postProcessing/dataConversion/foamToVTK/convertProcessorPatches.H
new file mode 100644
index 0000000000..45ead1d6b7
--- /dev/null
+++ b/applications/utilities/postProcessing/dataConversion/foamToVTK/convertProcessorPatches.H
@@ -0,0 +1,215 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration |
+ \\ / A nd | Copyright (C) 2019 OpenCFD Ltd.
+ \\/ M anipulation |
+-------------------------------------------------------------------------------
+License
+ This file is part of OpenFOAM.
+
+ OpenFOAM is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ OpenFOAM 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 General Public License
+ along with OpenFOAM. If not, see .
+
+Description
+ Code chunk for converting volume fields on processor boundaries,
+ included by foamToVTK.
+
+\*---------------------------------------------------------------------------*/
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+// Generate processor/processorN/procBoundary
+
+{
+ using reportFields = foamToVtkReportFields;
+
+ const label nVolFields =
+ (
+ objects.count(stringListOps::foundOp(fieldTypes::volume))
+ );
+
+ reportFields::volume(Info, objects);
+
+ // Setup for the vtm writer.
+
+ fileName vtmOutputBase
+ (
+ outputDir/regionPrefix/vtkName + timeDesc
+ );
+
+ // Naming
+ const auto subDirNaming =
+ [](const label i) -> fileName
+ { return "processor" / ("processor" + Foam::name(i)); };
+
+
+ // Dummy writer.
+ autoPtr internalWriter;
+
+ // Setup the patch writers
+ PtrList patchWriters;
+
+ const polyBoundaryMesh& patches = mesh.boundaryMesh();
+
+ labelList patchIds =
+ identity
+ (
+ patches.size()-patches.nNonProcessor(),
+ patches.nNonProcessor()
+ );
+
+ forAll(patchIds, i)
+ {
+ if (!isA(patches[patchIds[i]]))
+ {
+ patchIds.resize(i);
+ break;
+ }
+ }
+
+ patchWriters.resize(patchIds.size());
+
+ label nPatchWriters = 0;
+
+ List procPatchNames(Pstream::nProcs());
+
+ procPatchNames[Pstream::myProcNo()].resize(patchIds.size());
+
+ for (const label patchId : patchIds)
+ {
+ const polyPatch& pp = patches[patchId];
+
+ auto writer = autoPtr::New
+ (
+ meshProxy.mesh(),
+ labelList(one(), pp.index()),
+ writeOpts,
+ nearCellValue,
+ (
+ vtmOutputBase
+ / subDirNaming(Pstream::myProcNo())
+ / pp.name()
+ ),
+ false // This MUST be non-parallel (serial only)
+ );
+
+ procPatchNames[Pstream::myProcNo()][nPatchWriters] = pp.name();
+
+ writer->writeTimeValue(timeValue);
+ writer->writeGeometry();
+
+ // Transfer writer to list for later use
+ patchWriters.set(nPatchWriters++, writer);
+ }
+ patchWriters.resize(nPatchWriters);
+
+
+ Pstream::gatherList(procPatchNames);
+
+ // CellData
+ {
+ for (vtk::patchWriter& writer : patchWriters)
+ {
+ writer.beginCellData
+ (
+ 1 + (Pstream::parRun() ? 2 : 0)
+ + nVolFields
+ );
+ writer.writePatchIDs();
+ writer.writeProcIDs();
+ writer.writeNeighIDs();
+ }
+
+ writeAllVolFields
+ (
+ internalWriter,
+ patchWriters,
+ meshProxy,
+ objects,
+ true // syncPar
+ );
+
+ // End CellData is implicit
+ }
+
+
+ // Finish writers
+ if (internalWriter.valid())
+ {
+ internalWriter->close();
+ }
+
+ for (vtk::patchWriter& writer : patchWriters)
+ {
+ writer.close();
+ }
+
+ patchWriters.clear();
+
+
+ // Collective output
+
+ const label nProcPatches = returnReduce(nPatchWriters, sumOp