From 82fdeaf679c4911223cc3394a8041b334416ad8d Mon Sep 17 00:00:00 2001
From: mattijs <mattijs>
Date: Mon, 14 Jun 2021 16:33:30 +0100
Subject: [PATCH] BUG: redistributePar: preserve zone ordering. Fixes #2120

---
 .../meshes/polyMesh/zones/zone/zone.H         |  6 +++
 .../fvMeshDistribute/fvMeshDistribute.C       | 30 +++++++++---
 .../fvMeshDistribute/fvMeshDistribute.H       |  8 ++++
 .../fvMeshDistributeTemplates.C               | 47 +++++++++++++++++++
 4 files changed, 84 insertions(+), 7 deletions(-)

diff --git a/src/OpenFOAM/meshes/polyMesh/zones/zone/zone.H b/src/OpenFOAM/meshes/polyMesh/zones/zone/zone.H
index 57e528a29a1..d82b67199fc 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 9745cb61db1..24c4a537c14 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 1c4c7d518a1..e14565ccde4 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 ab7395d6651..bda893b7e6d 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)
 {
-- 
GitLab