diff --git a/applications/utilities/mesh/manipulation/reorderPatches/Make/files b/applications/utilities/mesh/manipulation/reorderPatches/Make/files
new file mode 100644
index 0000000000..8b50968e11
--- /dev/null
+++ b/applications/utilities/mesh/manipulation/reorderPatches/Make/files
@@ -0,0 +1,3 @@
+reorderPatches.C
+
+EXE = $(FOAM_APPBIN)/reorderPatches
diff --git a/applications/utilities/mesh/manipulation/reorderPatches/Make/options b/applications/utilities/mesh/manipulation/reorderPatches/Make/options
new file mode 100644
index 0000000000..6946273d27
--- /dev/null
+++ b/applications/utilities/mesh/manipulation/reorderPatches/Make/options
@@ -0,0 +1,10 @@
+EXE_INC = \
+ -I$(LIB_SRC)/polyTopoChange/lnInclude \
+ -I$(LIB_SRC)/meshTools/lnInclude \
+ -I$(LIB_SRC)/finiteVolume/lnInclude
+
+EXE_LIBS = \
+ -lpolyTopoChange \
+ -lmeshTools \
+ -lfiniteVolume \
+ -lgenericFvFields
diff --git a/applications/utilities/mesh/manipulation/reorderPatches/reorderPatches.C b/applications/utilities/mesh/manipulation/reorderPatches/reorderPatches.C
new file mode 100644
index 0000000000..bfd69a775e
--- /dev/null
+++ b/applications/utilities/mesh/manipulation/reorderPatches/reorderPatches.C
@@ -0,0 +1,256 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration | Website: https://openfoam.org
+ \\ / A nd | Copyright (C) 2024 OpenFOAM Foundation
+ \\/ 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 .
+
+Application
+ reorderPatches
+
+Description
+ Utility to reorder the patches of a case
+
+ The new patch order may be specified directly as a list of patch names
+ following the -patchOrder option or from the boundary file of a reference
+ case specified using the -referenceCase option with or without the
+ -referenceRegion option.
+
+ This utility run either serial or parallel but either way the reference
+ case boundary file is read from the constant directory.
+
+Usage
+ \b reorderPatches
+
+ Options:
+ - \par -patchOrder \
+ Specify the list of patch names in the new order.
+
+ - \par -referenceCase \
+ Specify the reference case path
+
+ - \par -referenceRegion \
+ Specify an alternative mesh region for the reference case.
+ If -referenceCase is not specified the current case is used.
+
+ - \par -overwrite \n
+ Replace the old mesh with the new one, rather than writing the new one
+ into a separate time directory
+
+ - \par -region \
+ Specify an alternative mesh region.
+
+\*---------------------------------------------------------------------------*/
+
+#include "argList.H"
+#include "fvMesh.H"
+#include "polyBoundaryMeshEntries.H"
+#include "timeSelector.H"
+
+using namespace Foam;
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+int main(int argc, char *argv[])
+{
+ timeSelector::addOptions(true, false);
+
+ argList::addNote
+ (
+ "Stitch the faces on the specified patch pairs\n"
+ "converting the overlapping patch faces into internal faces.\n"
+ );
+
+ #include "addOverwriteOption.H"
+ #include "addRegionOption.H"
+
+ argList::addOption
+ (
+ "patchOrder",
+ "wordList",
+ "specify the list of patch names in the new order"
+ );
+
+ argList::addOption
+ (
+ "referenceCase",
+ "fileName",
+ "specify the reference case path"
+ );
+
+ argList::addOption
+ (
+ "referenceRegion",
+ "word",
+ "specify the reference region"
+ );
+
+ #include "setRootCase.H"
+
+ wordList referencePatchNames;
+
+ if (args.optionFound("patchOrder"))
+ {
+ args.optionLookup("patchOrder")() >> referencePatchNames;
+ }
+ else if
+ (
+ args.optionFound("referenceCase")
+ || args.optionFound("referenceRegion")
+ )
+ {
+ const fileName referenceCasePath
+ (
+ args.optionLookupOrDefault("referenceCase", args.path())
+ );
+ const fileName rootDirReference = referenceCasePath.path().toAbsolute();
+ const fileName caseDirReference = referenceCasePath.name();
+
+ const string caseDirOrig = getEnv("FOAM_CASE");
+ const string caseNameOrig = getEnv("FOAM_CASENAME");
+ setEnv("FOAM_CASE", rootDirReference/caseDirReference, true);
+ setEnv("FOAM_CASENAME", caseDirReference, true);
+ Time referenceRunTime
+ (
+ Time::controlDictName,
+ rootDirReference,
+ caseDirReference,
+ false
+ );
+ setEnv("FOAM_CASE", caseDirOrig, true);
+ setEnv("FOAM_CASENAME", caseNameOrig, true);
+
+ word referenceRegion;
+ if (args.optionFound("referenceRegion"))
+ {
+ referenceRegion = args["referenceRegion"];
+ Info<< "Reference region: " << referenceRegion << endl;
+ }
+
+ const fileName referenceMeshDir(referenceRegion/polyMesh::meshSubDir);
+
+ typeIOobject ioObj
+ (
+ "boundary",
+ referenceRunTime.findInstance
+ (
+ referenceMeshDir,
+ "boundary",
+ IOobject::MUST_READ
+ ),
+ referenceMeshDir,
+ referenceRunTime,
+ IOobject::MUST_READ,
+ IOobject::NO_WRITE,
+ false
+ );
+
+ if (ioObj.headerOk())
+ {
+ polyBoundaryMeshEntries patchEntries(ioObj);
+
+ referencePatchNames.setSize(patchEntries.size());
+
+ forAll(patchEntries, patchi)
+ {
+ referencePatchNames[patchi] = patchEntries[patchi].keyword();
+ }
+ }
+ else
+ {
+ FatalErrorInFunction
+ << "Cannot find or read the boundary file for reference case "
+ << nl
+ << " " << referenceCasePath
+ << exit(FatalError);
+ }
+ }
+ else
+ {
+ FatalErrorInFunction
+ << "Reference patch order not specified"
+ << exit(FatalError);
+ }
+
+ #include "createTimeNoFunctionObjects.H"
+ #include "createRegionMeshNoChangers.H"
+
+ // Select time if specified
+ timeSelector::selectIfPresent(runTime, args);
+
+ const bool overwrite = args.optionFound("overwrite");
+
+ const word oldInstance = mesh.pointsInstance();
+
+ if (!overwrite)
+ {
+ runTime++;
+ }
+
+ if
+ (
+ !Pstream::parRun()
+ && mesh.boundaryMesh().size() != referencePatchNames.size()
+ )
+ {
+ FatalErrorInFunction
+ << "Number of reference patches " << referencePatchNames.size()
+ << " is not equal to the number of patches in the mesh "
+ << mesh.boundaryMesh().size()
+ << exit(FatalError);
+ }
+
+ // Reorder the patches
+ labelList newToOldPatches(identityMap(mesh.boundaryMesh().size()));
+
+ forAll(referencePatchNames, patchi)
+ {
+ const label oldPatchi =
+ mesh.boundaryMesh().findIndex(referencePatchNames[patchi]);
+
+ if (oldPatchi != -1)
+ {
+ newToOldPatches[patchi] = oldPatchi;
+ }
+ else
+ {
+ FatalErrorInFunction
+ << "Cannot find reference patch " << referencePatchNames[patchi]
+ << " in the mesh which has patches "
+ << mesh.boundaryMesh().names()
+ << exit(FatalError);
+ }
+ }
+ mesh.reorderPatches(newToOldPatches, false);
+
+ if (overwrite)
+ {
+ mesh.setInstance(oldInstance);
+ }
+
+ Info<< "Writing mesh to " << mesh.facesInstance() << endl;
+ mesh.write();
+
+ Info<< "End\n" << endl;
+
+ return 0;
+}
+
+
+// ************************************************************************* //