diff --git a/src/OpenFOAM/meshes/polyMesh/zones/zone/zone.H b/src/OpenFOAM/meshes/polyMesh/zones/zone/zone.H
index 57e528a29a1283b14d7fd51a9d08a44f70c25ef0..d82b67199fc511cdaaad765964fc86c27c5852cf 100644
--- a/src/OpenFOAM/meshes/polyMesh/zones/zone/zone.H
+++ b/src/OpenFOAM/meshes/polyMesh/zones/zone/zone.H
@@ -172,6 +172,12 @@ public:
             return index_;
         }
 
+        //- Return the index of this zone in zone list
+        label& index()
+        {
+            return index_;
+        }
+
         //- Return a reference to the look-up map
         const Map<label>& lookupMap() const;
 
diff --git a/src/dynamicMesh/fvMeshDistribute/fvMeshDistribute.C b/src/dynamicMesh/fvMeshDistribute/fvMeshDistribute.C
index 9745cb61db1cdc4f9a121f52407dd359afdf3de4..24c4a537c14c7f7cc8e6c2b791b058f34518e651 100644
--- a/src/dynamicMesh/fvMeshDistribute/fvMeshDistribute.C
+++ b/src/dynamicMesh/fvMeshDistribute/fvMeshDistribute.C
@@ -201,14 +201,24 @@ Foam::wordList Foam::fvMeshDistribute::mergeWordList(const wordList& procNames)
     List<wordList> allNames(Pstream::nProcs());
     allNames[Pstream::myProcNo()] = procNames;
     Pstream::gatherList(allNames);
-    Pstream::scatterList(allNames);
 
-    wordHashSet mergedNames;
-    forAll(allNames, proci)
+    // Assume there are few zone names to merge. Use HashSet otherwise (but
+    // maintain ordering)
+    DynamicList<word> mergedNames;
+    if (Pstream::master())
     {
-        mergedNames.insert(allNames[proci]);
+        mergedNames = procNames;
+        for (const wordList& names : allNames)
+        {
+            for (const word& name : names)
+            {
+                mergedNames.appendUniq(name);
+            }
+        }
     }
-    return mergedNames.sortedToc();
+    Pstream::scatter(mergedNames);
+
+    return mergedNames;
 }
 
 
@@ -1932,11 +1942,17 @@ Foam::autoPtr<Foam::mapDistributePolyMesh> Foam::fvMeshDistribute::distribute
     }
 
 
-    // Collect any zone names
+    // Collect any zone names over all processors and shuffle zones accordingly
+    // Note that this is not necessary for redistributePar since that already
+    // checks for it. However other use (e.g. mesh generators) might not.
     const wordList pointZoneNames(mergeWordList(mesh_.pointZones().names()));
+    reorderZones<pointZone>(pointZoneNames, mesh_.pointZones());
+
     const wordList faceZoneNames(mergeWordList(mesh_.faceZones().names()));
-    const wordList cellZoneNames(mergeWordList(mesh_.cellZones().names()));
+    reorderZones<faceZone>(faceZoneNames, mesh_.faceZones());
 
+    const wordList cellZoneNames(mergeWordList(mesh_.cellZones().names()));
+    reorderZones<cellZone>(cellZoneNames, mesh_.cellZones());
 
 
     // Local environment of all boundary faces
diff --git a/src/dynamicMesh/fvMeshDistribute/fvMeshDistribute.H b/src/dynamicMesh/fvMeshDistribute/fvMeshDistribute.H
index 1c4c7d518a1863c390c99efdebafb4d5331eb6e5..e14565ccde4231ca33327703d513fb2366a9ba6c 100644
--- a/src/dynamicMesh/fvMeshDistribute/fvMeshDistribute.H
+++ b/src/dynamicMesh/fvMeshDistribute/fvMeshDistribute.H
@@ -97,6 +97,14 @@ class fvMeshDistribute
         //- Merge wordlists over all processors
         static wordList mergeWordList(const wordList&);
 
+        //- Reorder zones according to names
+        template<class ZoneType, class ZoneMesh>
+        void reorderZones
+        (
+            const wordList& zoneNames,
+            ZoneMesh& zones
+        );
+
 
         // Patch handling
 
diff --git a/src/dynamicMesh/fvMeshDistribute/fvMeshDistributeTemplates.C b/src/dynamicMesh/fvMeshDistribute/fvMeshDistributeTemplates.C
index ab7395d6651ad8f8ca625956a154a22e2424f0b9..bda893b7e6dd3d89af831301913bad107dd36342 100644
--- a/src/dynamicMesh/fvMeshDistribute/fvMeshDistributeTemplates.C
+++ b/src/dynamicMesh/fvMeshDistribute/fvMeshDistributeTemplates.C
@@ -30,6 +30,53 @@ License
 
 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
 
+template<class ZoneType, class ZoneMesh>
+void Foam::fvMeshDistribute::reorderZones
+(
+    const wordList& zoneNames,
+    ZoneMesh& zones
+)
+{
+    zones.clearAddressing();
+
+    // Shift old ones to new position
+    UPtrList<ZoneType> newZonePtrs(zoneNames.size());
+    forAll(zones, zonei)
+    {
+        auto* zonePtr = zones.get(zonei);
+        if (!zonePtr)
+        {
+            FatalErrorInFunction << "Problem with zones " << zones.names()
+                << exit(FatalError);
+        }
+        const label newIndex = zoneNames.find(zonePtr->name());
+        zonePtr->index() = newIndex;
+        newZonePtrs.set(newIndex, zonePtr);
+    }
+
+    // Add empty zones for unknown ones
+    forAll(newZonePtrs, i)
+    {
+        if (!newZonePtrs.get(i))
+        {
+            newZonePtrs.set
+            (
+                i,
+                new ZoneType
+                (
+                    zoneNames[i],
+                    i,
+                    zones
+                )
+            );
+        }
+    }
+
+    // Transfer
+    zones.swap(newZonePtrs);
+}
+
+
 template<class GeoField>
 void Foam::fvMeshDistribute::printIntFieldInfo(const fvMesh& mesh)
 {