From 2745cd7544dcc4614442195efcd709122b7c87bf Mon Sep 17 00:00:00 2001
From: mattijs <mattijs>
Date: Tue, 4 Dec 2012 12:02:45 +0000
Subject: [PATCH] ENH: createBaffles: create patches and patchFields

---
 .../manipulation/createBaffles/Make/files     |   4 +
 .../manipulation/createBaffles/Make/options   |   1 +
 .../createBaffles/createBaffles.C             | 721 +++++++++++-------
 .../createBaffles/createBafflesDict           | 189 +++++
 .../faceSelection/faceSelection.C             | 111 +++
 .../faceSelection/faceSelection.H             | 156 ++++
 .../faceSelection/faceZoneSelection.C         | 108 +++
 .../faceSelection/faceZoneSelection.H         | 114 +++
 .../searchableSurfaceSelection.C              | 172 +++++
 .../searchableSurfaceSelection.H              | 106 +++
 10 files changed, 1426 insertions(+), 256 deletions(-)
 create mode 100644 applications/utilities/mesh/manipulation/createBaffles/createBafflesDict
 create mode 100644 applications/utilities/mesh/manipulation/createBaffles/faceSelection/faceSelection.C
 create mode 100644 applications/utilities/mesh/manipulation/createBaffles/faceSelection/faceSelection.H
 create mode 100644 applications/utilities/mesh/manipulation/createBaffles/faceSelection/faceZoneSelection.C
 create mode 100644 applications/utilities/mesh/manipulation/createBaffles/faceSelection/faceZoneSelection.H
 create mode 100644 applications/utilities/mesh/manipulation/createBaffles/faceSelection/searchableSurfaceSelection.C
 create mode 100644 applications/utilities/mesh/manipulation/createBaffles/faceSelection/searchableSurfaceSelection.H

diff --git a/applications/utilities/mesh/manipulation/createBaffles/Make/files b/applications/utilities/mesh/manipulation/createBaffles/Make/files
index 4d4c0ea538d..734f2bce764 100644
--- a/applications/utilities/mesh/manipulation/createBaffles/Make/files
+++ b/applications/utilities/mesh/manipulation/createBaffles/Make/files
@@ -1,3 +1,7 @@
+faceSelection/faceSelection.C
+faceSelection/faceZoneSelection.C
+faceSelection/searchableSurfaceSelection.C
+
 createBaffles.C
 
 EXE = $(FOAM_APPBIN)/createBaffles
diff --git a/applications/utilities/mesh/manipulation/createBaffles/Make/options b/applications/utilities/mesh/manipulation/createBaffles/Make/options
index f7e0c60fede..3c8db281299 100644
--- a/applications/utilities/mesh/manipulation/createBaffles/Make/options
+++ b/applications/utilities/mesh/manipulation/createBaffles/Make/options
@@ -1,4 +1,5 @@
 EXE_INC = \
+    -IfaceSelection \
     -I$(LIB_SRC)/finiteVolume/lnInclude \
     -I$(LIB_SRC)/dynamicMesh/lnInclude \
     -I$(LIB_SRC)/meshTools/lnInclude
diff --git a/applications/utilities/mesh/manipulation/createBaffles/createBaffles.C b/applications/utilities/mesh/manipulation/createBaffles/createBaffles.C
index 6fb57aa027c..c2e2a06ebb9 100644
--- a/applications/utilities/mesh/manipulation/createBaffles/createBaffles.C
+++ b/applications/utilities/mesh/manipulation/createBaffles/createBaffles.C
@@ -26,25 +26,26 @@ Description
     mergeOrSplitBaffles.
 
     Note: if any coupled patch face is selected for baffling the opposite
-    member has to be selected for baffling as well. Note that this
-    is the same as repatching. This was added only for convenience so
-    you don't have to filter coupled boundary out of your set.
+    member has to be selected for baffling as well.
+
+    - if the patch already exists will not override it nor its fields
+    - if the patch does not exist it will be created together with 'calculated'
+      patchfields unless the field is mentioned in the patchFields section.
 
 \*---------------------------------------------------------------------------*/
 
-#include "syncTools.H"
 #include "argList.H"
 #include "Time.H"
-#include "faceSet.H"
 #include "polyTopoChange.H"
 #include "polyModifyFace.H"
 #include "polyAddFace.H"
 #include "ReadFields.H"
 #include "volFields.H"
 #include "surfaceFields.H"
-#include "ZoneIDs.H"
 #include "fvMeshMapper.H"
-#include "SetPatchFields.H"
+#include "faceSelection.H"
+
+#include "fvMeshTools.H"
 
 using namespace Foam;
 
@@ -107,21 +108,6 @@ void modifyOrAddFace
 }
 
 
-label findPatchID(const polyMesh& mesh, const word& name)
-{
-    const label patchI = mesh.boundaryMesh().findPatchID(name);
-
-    if (patchI == -1)
-    {
-        FatalErrorIn("findPatchID(const polyMesh&, const word&)")
-            << "Cannot find patch " << name << endl
-            << "Valid patches are " << mesh.boundaryMesh().names()
-            << exit(FatalError);
-    }
-    return patchI;
-}
-
-
 // Main program:
 
 int main(int argc, char *argv[])
@@ -129,102 +115,84 @@ int main(int argc, char *argv[])
     argList::addNote
     (
         "Makes internal faces into boundary faces.\n"
-        "Does not duplicate points, unlike mergeOrSplitBaffles."
+        "Does not duplicate points."
     );
 
     #include "addOverwriteOption.H"
-    #include "addRegionOption.H"
-
-    argList::validArgs.append("faceZone");
-    argList::validArgs.append("(masterPatch slavePatch)");
     argList::addOption
     (
-        "additionalPatches",
-        "((master2 slave2) .. (masterN slaveN))"
-    );
-    argList::addBoolOption
-    (
-        "internalFacesOnly",
-        "do not convert boundary faces"
-    );
-    argList::addBoolOption
-    (
-        "updateFields",
-        "update fields to include new patches:"
-        " NOTE: updated field values may need to be edited"
+        "dict",
+        "file",
+        "specify alternative dictionary for the createBaffles description"
     );
-
+    #include "addRegionOption.H"
     #include "setRootCase.H"
     #include "createTime.H"
     runTime.functionObjects().off();
     #include "createNamedMesh.H"
 
-    const word oldInstance = mesh.pointsInstance();
-
-    const polyBoundaryMesh& patches = mesh.boundaryMesh();
-    const faceZoneMesh& faceZones = mesh.faceZones();
-
-    // Faces to baffle
-    faceZoneID zoneID(args.additionalArgs()[0], faceZones);
-
-    Info<< "Converting faces on zone " << zoneID.name()
-        << " into baffles." << nl << endl;
 
-    if (zoneID.index() == -1)
-    {
-        FatalErrorIn(args.executable()) << "Cannot find faceZone "
-            << zoneID.name() << endl
-            << "Valid zones are " << faceZones.names()
-            << exit(FatalError);
-    }
-
-    const faceZone& fZone = faceZones[zoneID.index()];
-
-    Info<< "Found " << returnReduce(fZone.size(), sumOp<label>())
-        << " faces on zone " << zoneID.name() << nl << endl;
+    const bool overwrite = args.optionFound("overwrite");
 
-    // Make sure patches and zoneFaces are synchronised across couples
-    patches.checkParallelSync(true);
-    fZone.checkParallelSync(true);
+    const word oldInstance = mesh.pointsInstance();
 
-    // Patches to put baffles into
-    DynamicList<label> newMasterPatches(1);
-    DynamicList<label> newSlavePatches(1);
+    const word dictName
+    (
+        args.optionLookupOrDefault<word>
+        (
+            "dict",
+            "createBafflesDict"
+        )
+    );
 
-    const Pair<word> patchNames(IStringStream(args.additionalArgs()[1])());
-    newMasterPatches.append(findPatchID(mesh, patchNames[0]));
-    newSlavePatches.append(findPatchID(mesh, patchNames[1]));
-    Info<< "Using master patch " << patchNames[0]
-        << " at index " << newMasterPatches[0] << endl;
-    Info<< "Using slave patch " << patchNames[1]
-        << " at index " << newSlavePatches[0] << endl;
+    Switch internalFacesOnly(false);
 
+    Switch noFields(false);
 
-    // Additional patches
-    if (args.optionFound("additionalPatches"))
+    PtrList<faceSelection> selectors;
     {
-        const List<Pair<word> > patchNames
+        Info<< "Reading baffle criteria from " << dictName << nl << endl;
+        IOdictionary dict
         (
-            args.optionLookup("additionalPatches")()
+            IOobject
+            (
+                dictName,
+                mesh.time().system(),
+                mesh,
+                IOobject::MUST_READ,
+                IOobject::NO_WRITE
+            )
         );
 
-        newMasterPatches.reserve(patchNames.size() + 1);
-        newSlavePatches.reserve(patchNames.size() + 1);
-        forAll(patchNames, i)
+        dict.lookup("internalFacesOnly") >> internalFacesOnly;
+        noFields = dict.lookupOrDefault("noFields", false);
+
+        const dictionary& selectionsDict = dict.subDict("baffles");
+
+        label n = 0;
+        forAllConstIter(dictionary, selectionsDict, iter)
         {
-            newMasterPatches.append(findPatchID(mesh, patchNames[i][0]));
-            newSlavePatches.append(findPatchID(mesh, patchNames[i][1]));
-            Info<< "Using additional patches " << patchNames[i]
-                << " at indices " << newMasterPatches.last()
-                << " and " << newSlavePatches.last()
-                << endl;
+            if (iter().isDict())
+            {
+                n++;
+            }
+        }
+        selectors.setSize(n);
+        n = 0;
+        forAllConstIter(dictionary, selectionsDict, iter)
+        {
+            if (iter().isDict())
+            {
+                selectors.set
+                (
+                    n++,
+                    faceSelection::New(iter().keyword(), mesh, iter().dict())
+                );
+            }
         }
     }
 
 
-    const bool overwrite = args.optionFound("overwrite");
-    const bool internalFacesOnly = args.optionFound("internalFacesOnly");
-
     if (internalFacesOnly)
     {
         Info<< "Not converting faces on non-coupled patches." << nl << endl;
@@ -237,208 +205,433 @@ int main(int argc, char *argv[])
     // Read vol fields.
     Info<< "Reading geometric fields" << nl << endl;
     PtrList<volScalarField> vsFlds;
-    ReadFields(mesh, objects, vsFlds);
+    if (!noFields) ReadFields(mesh, objects, vsFlds);
 
     PtrList<volVectorField> vvFlds;
-    ReadFields(mesh, objects, vvFlds);
+    if (!noFields) ReadFields(mesh, objects, vvFlds);
 
     PtrList<volSphericalTensorField> vstFlds;
-    ReadFields(mesh, objects, vstFlds);
+    if (!noFields) ReadFields(mesh, objects, vstFlds);
 
     PtrList<volSymmTensorField> vsymtFlds;
-    ReadFields(mesh, objects, vsymtFlds);
+    if (!noFields) ReadFields(mesh, objects, vsymtFlds);
 
     PtrList<volTensorField> vtFlds;
-    ReadFields(mesh, objects, vtFlds);
+    if (!noFields) ReadFields(mesh, objects, vtFlds);
 
     // Read surface fields.
 
     PtrList<surfaceScalarField> ssFlds;
-    ReadFields(mesh, objects, ssFlds);
+    if (!noFields) ReadFields(mesh, objects, ssFlds);
 
     PtrList<surfaceVectorField> svFlds;
-    ReadFields(mesh, objects, svFlds);
+    if (!noFields) ReadFields(mesh, objects, svFlds);
 
     PtrList<surfaceSphericalTensorField> sstFlds;
-    ReadFields(mesh, objects, sstFlds);
+    if (!noFields) ReadFields(mesh, objects, sstFlds);
 
     PtrList<surfaceSymmTensorField> ssymtFlds;
-    ReadFields(mesh, objects, ssymtFlds);
+    if (!noFields) ReadFields(mesh, objects, ssymtFlds);
 
     PtrList<surfaceTensorField> stFlds;
-    ReadFields(mesh, objects, stFlds);
+    if (!noFields) ReadFields(mesh, objects, stFlds);
 
 
-    // Mesh change container
-    polyTopoChange meshMod(mesh);
 
 
-    // Do the actual changes. Note:
-    // - loop in incrementing face order (not necessary if faceZone ordered).
-    //   Preserves any existing ordering on patch faces.
-    // - two passes, do non-flip faces first and flip faces second. This
-    //   guarantees that when e.g. creating a cyclic all faces from one
-    //   side come first and faces from the other side next.
+    // Creating (if necessary) baffles
+    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-    // Whether first use of face (modify) or consecutive (add)
-    PackedBoolList modifiedFace(mesh.nFaces());
-    label nModified = 0;
+    forAll(selectors, selectorI)
+    {
+        const word& name = selectors[selectorI].name();
 
-    forAll(newMasterPatches, i)
+        if (mesh.faceZones().findZoneID(name) == -1)
+        {
+            mesh.faceZones().clearAddressing();
+            label sz = mesh.faceZones().size();
+
+            labelList addr(0);
+            boolList flip(0);
+            mesh.faceZones().setSize(sz+1);
+            mesh.faceZones().set
+            (
+                sz,
+                new faceZone(name, addr, flip, sz, mesh.faceZones())
+            );
+        }
+    }
+
+
+    // Select faces
+    // ~~~~~~~~~~~~
+
+    //- Per face zoneID it is in and flip status.
+    labelList faceToZoneID(mesh.nFaces(), -1);
+    boolList faceToFlip(mesh.nFaces(), false);
+    forAll(selectors, selectorI)
     {
-        // Pass 1. Do selected side of zone
-        // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+        const word& name = selectors[selectorI].name();
+        label zoneID = mesh.faceZones().findZoneID(name);
+
+        selectors[selectorI].select(zoneID, faceToZoneID, faceToFlip);
+    }
 
-        for (label faceI = 0; faceI < mesh.nInternalFaces(); faceI++)
+    // Add faces to faceZones
+    labelList nFaces(mesh.faceZones().size(), 0);
+    forAll(faceToZoneID, faceI)
+    {
+        label zoneID = faceToZoneID[faceI];
+        if (zoneID != -1)
         {
-            label zoneFaceI = fZone.whichFace(faceI);
+            nFaces[zoneID]++;
+        }
+    }
 
-            if (zoneFaceI != -1)
+    forAll(selectors, selectorI)
+    {
+        const word& name = selectors[selectorI].name();
+        label zoneID = mesh.faceZones().findZoneID(name);
+
+        label& n = nFaces[zoneID];
+        labelList addr(n);
+        boolList flip(n);
+        n = 0;
+        forAll(faceToZoneID, faceI)
+        {
+            label zone = faceToZoneID[faceI];
+            if (zone == zoneID)
             {
-                if (!fZone.flipMap()[zoneFaceI])
-                {
-                    // Use owner side of face
-                    modifyOrAddFace
-                    (
-                        meshMod,
-                        mesh.faces()[faceI],    // modified face
-                        faceI,                  // label of face
-                        mesh.faceOwner()[faceI],// owner
-                        false,                  // face flip
-                        newMasterPatches[i],    // patch for face
-                        zoneID.index(),         // zone for face
-                        false,                  // face flip in zone
-                        modifiedFace            // modify or add status
-                    );
-                }
-                else
-                {
-                    // Use neighbour side of face
-                    modifyOrAddFace
-                    (
-                        meshMod,
-                        mesh.faces()[faceI].reverseFace(),  // modified face
-                        faceI,                      // label of face
-                        mesh.faceNeighbour()[faceI],// owner
-                        true,                       // face flip
-                        newMasterPatches[i],        // patch for face
-                        zoneID.index(),             // zone for face
-                        true,                       // face flip in zone
-                        modifiedFace                // modify or add status
-                    );
-                }
-
-                nModified++;
+                addr[n] = faceI;
+                flip[n] = faceToFlip[faceI];
+                n++;
             }
         }
 
+        Info<< "Created zone " << name
+            << " at index " << zoneID
+            << " with " << n << " faces" << endl;
 
-        // Pass 2. Do other side of zone
-        // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+        mesh.faceZones().set
+        (
+            zoneID,
+            new faceZone(name, addr, flip, zoneID, mesh.faceZones())
+        );
+    }
 
-        for (label faceI = 0; faceI < mesh.nInternalFaces(); faceI++)
+
+
+    // Count patches to add
+    // ~~~~~~~~~~~~~~~~~~~~
+    HashSet<word> bafflePatches;
+    {
+        forAll(selectors, selectorI)
         {
-            label zoneFaceI = fZone.whichFace(faceI);
+            const dictionary& patchSources
+            (
+                selectors[selectorI].dict().subDict("patches")
+            );
+            forAllConstIter(dictionary, patchSources, iter)
+            {
+                //const word& patchName = iter().keyword();
+                const word patchName(iter().dict()["name"]);
+                bafflePatches.insert(patchName);
+            }
+        }
+    }
+
+
+
+    // Create baffles
+    // ~~~~~~~~~~~~~~
+    // Is done in multiple steps
+    // - create patches with 'calculated' patchFields
+    // - move faces into these patches
+    // - change the patchFields to the wanted type
+    // This order is done so e.g. fixedJump works:
+    // - you cannot create patchfields at the same time as patches since
+    //   they do an evaluate upon construction
+    // - you want to create the patchField only after you have faces
+    //   so you don't get the 'create-from-nothing' mapping problem.
 
-            if (zoneFaceI != -1)
+
+    // Pass 1: add patches
+    // ~~~~~~~~~~~~~~~~~~~
+
+    //HashSet<word> addedPatches;
+    {
+        const polyBoundaryMesh& pbm = mesh.boundaryMesh();
+        forAll(selectors, selectorI)
+        {
+            const dictionary& patchSources
+            (
+                selectors[selectorI].dict().subDict("patches")
+            );
+            forAllConstIter(dictionary, patchSources, iter)
             {
-                if (!fZone.flipMap()[zoneFaceI])
+                //const word& patchName = iter().keyword();
+                const word patchName(iter().dict()["name"]);
+
+                label destPatchI = pbm.findPatchID(patchName);
+
+                if (destPatchI == -1)
                 {
-                    // Use neighbour side of face
-                    modifyOrAddFace
+                    dictionary patchDict = iter().dict();
+                    patchDict.set("nFaces", 0);
+                    patchDict.set("startFace", 0);
+
+                    Info<< "Adding new patch " << patchName
+                        << " from " << patchDict << endl;
+
+                    autoPtr<polyPatch> ppPtr
                     (
-                        meshMod,
-                        mesh.faces()[faceI].reverseFace(),  // modified face
-                        faceI,                              // label of face
-                        mesh.faceNeighbour()[faceI],        // owner
-                        true,                               // face flip
-                        newSlavePatches[i],                 // patch for face
-                        zoneID.index(),                     // zone for face
-                        true,                               // face flip in zone
-                        modifiedFace                        // modify or add
+                        polyPatch::New
+                        (
+                            patchName,
+                            patchDict,
+                            0,
+                            pbm
+                        )
                     );
+
+                    // Add patch, create calculated everywhere
+                    fvMeshTools::addPatch
+                    (
+                        mesh,
+                        ppPtr(),
+                        dictionary(),   // do not set specialised patchFields
+                        calculatedFvPatchField<scalar>::typeName,
+                        true            // parallel sync'ed addition
+                    );
+
+                    //addedPatches.insert(patchName);
                 }
                 else
                 {
-                    // Use owner side of face
-                    modifyOrAddFace
-                    (
-                        meshMod,
-                        mesh.faces()[faceI],    // modified face
-                        faceI,                  // label of face
-                        mesh.faceOwner()[faceI],// owner
-                        false,                  // face flip
-                        newSlavePatches[i],     // patch for face
-                        zoneID.index(),         // zone for face
-                        false,                  // face flip in zone
-                        modifiedFace            // modify or add status
-                    );
+                    Info<< "Patch '" << patchName << "' already exists.  Only "
+                        << "moving patch faces - type will remain the same"
+                        << endl;
                 }
             }
         }
+    }
+
 
 
-        // Modify any boundary faces
-        // ~~~~~~~~~~~~~~~~~~~~~~~~~
+    // Make sure patches and zoneFaces are synchronised across couples
+    mesh.boundaryMesh().checkParallelSync(true);
+    mesh.faceZones().checkParallelSync(true);
 
-        // Normal boundary:
-        // - move to new patch. Might already be back-to-back baffle
-        // you want to add cyclic to. Do warn though.
-        //
-        // Processor boundary:
-        // - do not move to cyclic
-        // - add normal patches though.
 
-        // For warning once per patch.
-        labelHashSet patchWarned;
 
-        forAll(patches, patchI)
-        {
-            const polyPatch& pp = patches[patchI];
+    // Mesh change container
+    polyTopoChange meshMod(mesh);
+
+    const polyBoundaryMesh& pbm = mesh.boundaryMesh();
+
+
+    // Do the actual changes. Note:
+    // - loop in incrementing face order (not necessary if faceZone ordered).
+    //   Preserves any existing ordering on patch faces.
+    // - two passes, do non-flip faces first and flip faces second. This
+    //   guarantees that when e.g. creating a cyclic all faces from one
+    //   side come first and faces from the other side next.
+
+    // Whether first use of face (modify) or consecutive (add)
+    PackedBoolList modifiedFace(mesh.nFaces());
+    label nModified = 0;
+
+    forAll(selectors, selectorI)
+    {
+        const word& name = selectors[selectorI].name();
+        label zoneID = mesh.faceZones().findZoneID(name);
+        const faceZone& fZone = mesh.faceZones()[zoneID];
 
-            label newPatchI = newMasterPatches[i];
+        const dictionary& patchSources
+        (
+            selectors[selectorI].dict().subDict("patches")
+        );
+
+        DynamicList<label> newMasterPatches(patchSources.size());
+        DynamicList<label> newSlavePatches(patchSources.size());
+
+        bool master = true;
 
-            if (pp.coupled() && patches[newPatchI].coupled())
+        forAllConstIter(dictionary, patchSources, iter)
+        {
+            //const word& patchName = iter().keyword();
+            const word patchName(iter().dict()["name"]);
+            label patchI = pbm.findPatchID(patchName);
+            if (master)
             {
-                // Do not allow coupled faces to be moved to different coupled
-                // patches.
+                newMasterPatches.append(patchI);
             }
-            else if (pp.coupled() || !internalFacesOnly)
+            else
             {
-                forAll(pp, i)
-                {
-                    label faceI = pp.start()+i;
+                newSlavePatches.append(patchI);
+            }
+            master = !master;
+        }
 
-                    label zoneFaceI = fZone.whichFace(faceI);
 
-                    if (zoneFaceI != -1)
-                    {
-                        if (patchWarned.insert(patchI))
-                        {
-                            WarningIn(args.executable())
-                                << "Found boundary face (in patch " << pp.name()
-                                << ") in faceZone " << fZone.name()
-                                << " to convert to baffle patch "
-                                << patches[newPatchI].name()
-                                << endl
-                                << "    Run with -internalFacesOnly option"
-                                << " if you don't wish to convert"
-                                << " boundary faces." << endl;
-                        }
 
+        forAll(newMasterPatches, i)
+        {
+            // Pass 1. Do selected side of zone
+            // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+            for (label faceI = 0; faceI < mesh.nInternalFaces(); faceI++)
+            {
+                label zoneFaceI = fZone.whichFace(faceI);
+
+                if (zoneFaceI != -1)
+                {
+                    if (!fZone.flipMap()[zoneFaceI])
+                    {
+                        // Use owner side of face
                         modifyOrAddFace
                         (
                             meshMod,
-                            mesh.faces()[faceI],        // modified face
+                            mesh.faces()[faceI],    // modified face
+                            faceI,                  // label of face
+                            mesh.faceOwner()[faceI],// owner
+                            false,                  // face flip
+                            newMasterPatches[i],    // patch for face
+                            fZone.index(),          // zone for face
+                            false,                  // face flip in zone
+                            modifiedFace            // modify or add status
+                        );
+                    }
+                    else
+                    {
+                        // Use neighbour side of face
+                        modifyOrAddFace
+                        (
+                            meshMod,
+                            mesh.faces()[faceI].reverseFace(),  // modified face
                             faceI,                      // label of face
-                            mesh.faceOwner()[faceI],    // owner
-                            false,                      // face flip
-                            newPatchI,                  // patch for face
-                            zoneID.index(),             // zone for face
-                            fZone.flipMap()[zoneFaceI], // face flip in zone
+                            mesh.faceNeighbour()[faceI],// owner
+                            true,                       // face flip
+                            newMasterPatches[i],        // patch for face
+                            fZone.index(),              // zone for face
+                            true,                       // face flip in zone
                             modifiedFace                // modify or add status
                         );
-                        nModified++;
+                    }
+
+                    nModified++;
+                }
+            }
+
+
+            // Pass 2. Do other side of zone
+            // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+            for (label faceI = 0; faceI < mesh.nInternalFaces(); faceI++)
+            {
+                label zoneFaceI = fZone.whichFace(faceI);
+
+                if (zoneFaceI != -1)
+                {
+                    if (!fZone.flipMap()[zoneFaceI])
+                    {
+                        // Use neighbour side of face
+                        modifyOrAddFace
+                        (
+                            meshMod,
+                            mesh.faces()[faceI].reverseFace(),  // modified face
+                            faceI,                          // label of face
+                            mesh.faceNeighbour()[faceI],    // owner
+                            true,                           // face flip
+                            newSlavePatches[i],             // patch for face
+                            fZone.index(),                  // zone for face
+                            true,                           // face flip in zone
+                            modifiedFace                    // modify or add
+                        );
+                    }
+                    else
+                    {
+                        // Use owner side of face
+                        modifyOrAddFace
+                        (
+                            meshMod,
+                            mesh.faces()[faceI],    // modified face
+                            faceI,                  // label of face
+                            mesh.faceOwner()[faceI],// owner
+                            false,                  // face flip
+                            newSlavePatches[i],     // patch for face
+                            fZone.index(),          // zone for face
+                            false,                  // face flip in zone
+                            modifiedFace            // modify or add status
+                        );
+                    }
+                }
+            }
+
+
+            // Modify any boundary faces
+            // ~~~~~~~~~~~~~~~~~~~~~~~~~
+
+            // Normal boundary:
+            // - move to new patch. Might already be back-to-back baffle
+            // you want to add cyclic to. Do warn though.
+            //
+            // Processor boundary:
+            // - do not move to cyclic
+            // - add normal patches though.
+
+            // For warning once per patch.
+            labelHashSet patchWarned;
+
+            forAll(pbm, patchI)
+            {
+                const polyPatch& pp = pbm[patchI];
+
+                label newPatchI = newMasterPatches[i];
+
+                if (pp.coupled() && pbm[newPatchI].coupled())
+                {
+                    // Do not allow coupled faces to be moved to different
+                    // coupled patches.
+                }
+                else if (pp.coupled() || !internalFacesOnly)
+                {
+                    forAll(pp, i)
+                    {
+                        label faceI = pp.start()+i;
+
+                        label zoneFaceI = fZone.whichFace(faceI);
+
+                        if (zoneFaceI != -1)
+                        {
+                            if (patchWarned.insert(patchI))
+                            {
+                                WarningIn(args.executable())
+                                    << "Found boundary face (in patch "
+                                    << pp.name()
+                                    << ") in faceZone " << fZone.name()
+                                    << " to convert to baffle patch "
+                                    << pbm[newPatchI].name()
+                                    << endl
+                                    << "    Run with -internalFacesOnly option"
+                                    << " if you don't wish to convert"
+                                    << " boundary faces." << endl;
+                            }
+
+                            modifyOrAddFace
+                            (
+                                meshMod,
+                                mesh.faces()[faceI],        // modified face
+                                faceI,                      // label of face
+                                mesh.faceOwner()[faceI],    // owner
+                                false,                      // face flip
+                                newPatchI,                  // patch for face
+                                fZone.index(),              // zone for face
+                                fZone.flipMap()[zoneFaceI], // face flip in zone
+                                modifiedFace                // modify or add
+                            );
+                            nModified++;
+                        }
                     }
                 }
             }
@@ -447,7 +640,8 @@ int main(int argc, char *argv[])
 
 
     Info<< "Converted " << returnReduce(nModified, sumOp<label>())
-        << " faces into boundary faces on patches " << patchNames << nl << endl;
+        << " faces into boundary faces in patches "
+        << bafflePatches.sortedToc() << nl << endl;
 
     if (!overwrite)
     {
@@ -460,14 +654,20 @@ int main(int argc, char *argv[])
     // Update fields
     mesh.updateMesh(map);
 
+
+
     // Correct boundary faces mapped-out-of-nothing.
+    // This is just a hack to correct the value field.
     {
         fvMeshMapper mapper(mesh, map);
         bool hasWarned = false;
-        forAll(newMasterPatches, i)
+
+        forAllConstIter(HashSet<word>, bafflePatches, iter)
         {
-            label patchI = newMasterPatches[i];
+            label patchI = mesh.boundaryMesh().findPatchID(iter.key());
+
             const fvPatchMapper& pm = mapper.boundaryMap()[patchI];
+
             if (pm.sizeBeforeMapping() == 0)
             {
                 if (!hasWarned)
@@ -478,40 +678,48 @@ int main(int argc, char *argv[])
                         << "You might have to edit these fields." << endl;
                 }
 
-                SetPatchFields(vsFlds, patchI, pTraits<scalar>::zero);
-                SetPatchFields(vvFlds, patchI, pTraits<vector>::zero);
-                SetPatchFields(vstFlds, patchI, pTraits<sphericalTensor>::zero);
-                SetPatchFields(vsymtFlds, patchI, pTraits<symmTensor>::zero);
-                SetPatchFields(vtFlds, patchI, pTraits<tensor>::zero);
-
-                SetPatchFields(ssFlds, patchI, pTraits<scalar>::zero);
-                SetPatchFields(svFlds, patchI, pTraits<vector>::zero);
-                SetPatchFields(sstFlds, patchI, pTraits<sphericalTensor>::zero);
-                SetPatchFields(ssymtFlds, patchI, pTraits<symmTensor>::zero);
-                SetPatchFields(stFlds, patchI, pTraits<tensor>::zero);
+                fvMeshTools::zeroPatchFields(mesh, patchI);
             }
         }
-        forAll(newSlavePatches, i)
+    }
+
+
+    // Pass 2: change patchFields
+    // ~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    {
+        const polyBoundaryMesh& pbm = mesh.boundaryMesh();
+        forAll(selectors, selectorI)
         {
-            label patchI = newSlavePatches[i];
-            const fvPatchMapper& pm = mapper.boundaryMap()[patchI];
-            if (pm.sizeBeforeMapping() == 0)
+            const dictionary& patchSources
+            (
+                selectors[selectorI].dict().subDict("patches")
+            );
+            forAllConstIter(dictionary, patchSources, iter)
             {
-                SetPatchFields(vsFlds, patchI, pTraits<scalar>::zero);
-                SetPatchFields(vvFlds, patchI, pTraits<vector>::zero);
-                SetPatchFields(vstFlds, patchI, pTraits<sphericalTensor>::zero);
-                SetPatchFields(vsymtFlds, patchI, pTraits<symmTensor>::zero);
-                SetPatchFields(vtFlds, patchI, pTraits<tensor>::zero);
-
-                SetPatchFields(ssFlds, patchI, pTraits<scalar>::zero);
-                SetPatchFields(svFlds, patchI, pTraits<vector>::zero);
-                SetPatchFields(sstFlds, patchI, pTraits<sphericalTensor>::zero);
-                SetPatchFields(ssymtFlds, patchI, pTraits<symmTensor>::zero);
-                SetPatchFields(stFlds, patchI, pTraits<tensor>::zero);
+                //const word& patchName = iter().keyword();
+                const word patchName(iter().dict()["name"]);
+                label patchI = pbm.findPatchID(patchName);
+
+                if (iter().dict().found("patchFields"))
+                {
+                    const dictionary& patchFieldsDict = iter().dict().subDict
+                    (
+                        "patchFields"
+                    );
+
+                    fvMeshTools::setPatchFields
+                    (
+                        mesh,
+                        patchI,
+                        patchFieldsDict
+                    );
+                }
             }
         }
     }
 
+
     // Move mesh (since morphing might not do this)
     if (map().hasMotionPoints())
     {
@@ -522,6 +730,7 @@ int main(int argc, char *argv[])
     {
         mesh.setInstance(oldInstance);
     }
+
     Info<< "Writing mesh to " << runTime.timeName() << endl;
 
     mesh.write();
diff --git a/applications/utilities/mesh/manipulation/createBaffles/createBafflesDict b/applications/utilities/mesh/manipulation/createBaffles/createBafflesDict
new file mode 100644
index 00000000000..7a128adbb10
--- /dev/null
+++ b/applications/utilities/mesh/manipulation/createBaffles/createBafflesDict
@@ -0,0 +1,189 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  dev                                   |
+|   \\  /    A nd           | Web:      www.OpenFOAM.org                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      createBafflesDict;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+// Whether to convert internal faces only (so leave boundary faces intact).
+// This is only relevant if your face selection type can pick up boundary
+// faces.
+internalFacesOnly true;
+
+// Optionally do not read/convert/write any fields.
+//noFields true;
+
+
+// Baffles to create.
+baffles
+{
+    baffleFaces
+    {
+        //- Use predefined faceZone to select faces and orientation.
+        type        faceZone;
+        zoneName    baffleFaces;
+
+
+        //- Optional flip
+        //flip        false;
+
+        patches
+        {
+            master
+            {
+                //- Master side patch
+                name            baffles;
+                type            wall;
+
+                patchFields
+                {
+                    epsilon
+                    {
+                        type            epsilonWallFunction;
+                        Cmu             0.09;
+                        kappa           0.41;
+                        E               9.8;
+                        value           uniform 0;
+                    }
+                    k
+                    {
+                        type            kqRWallFunction;
+                        value           uniform 0;
+                    }
+                    nut
+                    {
+                        type            nutkWallFunction;
+                        Cmu             0.09;
+                        kappa           0.41;
+                        E               9.8;
+                        value           uniform 0;
+                    }
+                    nuTilda
+                    {
+                        type            zeroGradient;
+                    }
+                    p
+                    {
+                        type            zeroGradient;
+                    }
+                    U
+                    {
+                        type            fixedValue;
+                        value           uniform (0 0 0);
+                    }
+                }
+            }
+            slave
+            {
+                //- Slave side patch
+                name            baffles;
+                type            wall;
+
+                patchFields
+                {
+                    epsilon
+                    {
+                        type            epsilonWallFunction;
+                        Cmu             0.09;
+                        kappa           0.41;
+                        E               9.8;
+                        value           uniform 0;
+                    }
+                    k
+                    {
+                        type            kqRWallFunction;
+                        value           uniform 0;
+                    }
+                    nut
+                    {
+                        type            nutkWallFunction;
+                        Cmu             0.09;
+                        kappa           0.41;
+                        E               9.8;
+                        value           uniform 0;
+                    }
+                    nuTilda
+                    {
+                        type            zeroGradient;
+                    }
+                    p
+                    {
+                        type            zeroGradient;
+                    }
+                    U
+                    {
+                        type            fixedValue;
+                        value           uniform (0 0 0);
+                    }
+                }
+            }
+        }
+    }
+
+
+
+    cyclicFaces
+    {
+        //- Select faces and orientation through a searchableSurface
+        type        searchableSurface;
+        surface     searchablePlate;
+        origin      (0.099 -0.006 0.004);
+        span        (0 0.012 0.012);
+
+        patches
+        {
+            master
+            {
+                //- Master side patch
+
+                name            fan_half0;
+                type            cyclic;
+                neighbourPatch  fan_half1;
+
+                //- Optional override of added patchfields. If not specified
+                //  any added patchfields are of type calculated.
+                patchFields
+                {
+                    p
+                    {
+                        type            fan;
+                        patchType       cyclic;
+                        jump            uniform 0;
+                        value           uniform 0;
+                        jumpTable       polynomial 1((100 0));
+                    }
+                }
+            }
+            slave
+            {
+                //- Slave side patch
+
+                name            fan_half1;
+                type            cyclic;
+                neighbourPatch  fan_half0;
+
+                patchFields
+                {
+                    p
+                    {
+                        type            fan;
+                        patchType       cyclic;
+                        value           uniform 0;
+                    }
+                }
+            }
+        }
+    }
+}
+
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/manipulation/createBaffles/faceSelection/faceSelection.C b/applications/utilities/mesh/manipulation/createBaffles/faceSelection/faceSelection.C
new file mode 100644
index 00000000000..57a6b554c79
--- /dev/null
+++ b/applications/utilities/mesh/manipulation/createBaffles/faceSelection/faceSelection.C
@@ -0,0 +1,111 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2012 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 <http://www.gnu.org/licenses/>.
+
+\*---------------------------------------------------------------------------*/
+
+#include "faceSelection.H"
+#include "fvMesh.H"
+
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+namespace Foam
+{
+    defineTypeNameAndDebug(faceSelection, 0);
+    defineRunTimeSelectionTable(faceSelection, dictionary);
+}
+
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::faceSelection::faceSelection
+(
+    const word& name,
+    const fvMesh& mesh,
+    const dictionary& dict
+)
+:
+    name_(name),
+    mesh_(mesh),
+    dict_(dict),
+    flip_(dict.lookupOrDefault("flip", false))
+{}
+
+
+// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
+
+Foam::faceSelection::~faceSelection()
+{}
+
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+Foam::autoPtr<Foam::faceSelection> Foam::faceSelection::New
+(
+    const word& name,
+    const fvMesh& mesh,
+    const dictionary& dict
+)
+{
+    const word sampleType(dict.lookup("type"));
+
+    dictionaryConstructorTable::iterator cstrIter =
+        dictionaryConstructorTablePtr_->find(sampleType);
+
+    if (cstrIter == dictionaryConstructorTablePtr_->end())
+    {
+        FatalErrorIn
+        (
+            "faceSelection::New"
+            "(const word&, const fvMesh&, const dictionary&)"
+        )   << "Unknown faceSelection type "
+            << sampleType << nl << nl
+            << "Valid faceSelection types : " << endl
+            << dictionaryConstructorTablePtr_->sortedToc()
+            << exit(FatalError);
+    }
+
+    return autoPtr<faceSelection>(cstrIter()(name, mesh, dict));
+}
+
+
+void Foam::faceSelection::select
+(
+    const label zoneID,
+    labelList& faceToZoneID,
+    boolList& faceToFlip
+) const
+{
+    if (flip_)
+    {
+        forAll(faceToZoneID, faceI)
+        {
+            if (faceToZoneID[faceI] == zoneID)
+            {
+                faceToFlip[faceI] = !faceToFlip[faceI];
+            }
+        }
+    }
+}
+
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/manipulation/createBaffles/faceSelection/faceSelection.H b/applications/utilities/mesh/manipulation/createBaffles/faceSelection/faceSelection.H
new file mode 100644
index 00000000000..7be333f030f
--- /dev/null
+++ b/applications/utilities/mesh/manipulation/createBaffles/faceSelection/faceSelection.H
@@ -0,0 +1,156 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2012 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 <http://www.gnu.org/licenses/>.
+
+Class
+    Foam::faceSelection
+
+Description
+    Face selection method for createBaffles
+
+SourceFiles
+    faceSelection.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef faceSelection_H
+#define faceSelection_H
+
+#include "dictionary.H"
+#include "typeInfo.H"
+#include "runTimeSelectionTables.H"
+#include "autoPtr.H"
+#include "boolList.H"
+#include "labelList.H"
+#include "Switch.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+// Forward declaration of classes
+class fvMesh;
+
+/*---------------------------------------------------------------------------*\
+                         Class faceSelection Declaration
+\*---------------------------------------------------------------------------*/
+
+class faceSelection
+{
+protected:
+
+    // Protected data
+
+        //- Name
+        const word name_;
+
+        //- Reference to mesh
+        const fvMesh& mesh_;
+
+        //- Input dictionary
+        const dictionary dict_;
+
+        //- Switch direction?
+        const Switch flip_;
+
+public:
+
+    //- Runtime type information
+    TypeName("faceSelection");
+
+
+    // Declare run-time constructor selection table
+
+        declareRunTimeSelectionTable
+        (
+            autoPtr,
+            faceSelection,
+            dictionary,
+            (
+                const word& name,
+                const fvMesh& mesh,
+                const dictionary& dict
+            ),
+            (name, mesh, dict)
+        );
+
+
+    // Constructors
+
+        //- Construct from dictionary
+        faceSelection
+        (
+            const word& name,
+            const fvMesh& mesh,
+            const dictionary& dict
+        );
+
+        //- Clone
+        autoPtr<faceSelection> clone() const
+        {
+            notImplemented("autoPtr<faceSelection> clone() const");
+            return autoPtr<faceSelection>(NULL);
+        }
+
+
+    // Selectors
+
+        //- Return a reference to the selected faceSelection
+        static autoPtr<faceSelection> New
+        (
+            const word& name,
+            const fvMesh& mesh,
+            const dictionary& dict
+        );
+
+
+    //- Destructor
+    virtual ~faceSelection();
+
+
+    // Member Functions
+
+        const word& name() const
+        {
+            return name_;
+        }
+
+        const dictionary& dict() const
+        {
+            return dict_;
+        }
+
+        virtual void select(const label, labelList&, boolList&) const = 0;
+
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/manipulation/createBaffles/faceSelection/faceZoneSelection.C b/applications/utilities/mesh/manipulation/createBaffles/faceSelection/faceZoneSelection.C
new file mode 100644
index 00000000000..bdc6d84e67d
--- /dev/null
+++ b/applications/utilities/mesh/manipulation/createBaffles/faceSelection/faceZoneSelection.C
@@ -0,0 +1,108 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2012 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 <http://www.gnu.org/licenses/>.
+
+\*---------------------------------------------------------------------------*/
+
+#include "faceZoneSelection.H"
+#include "addToRunTimeSelectionTable.H"
+#include "fvMesh.H"
+
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+namespace Foam
+{
+namespace faceSelections
+{
+    defineTypeNameAndDebug(faceZoneSelection, 0);
+    addToRunTimeSelectionTable(faceSelection, faceZoneSelection, dictionary);
+}
+}
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::faceSelections::faceZoneSelection::faceZoneSelection
+(
+    const word& name,
+    const fvMesh& mesh,
+    const dictionary& dict
+)
+:
+    faceSelection(name, mesh, dict),
+    zoneName_(dict_.lookup("zoneName"))
+{}
+
+
+// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
+
+Foam::faceSelections::faceZoneSelection::~faceZoneSelection()
+{}
+
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+void Foam::faceSelections::faceZoneSelection::select
+(
+    const label zoneID,
+    labelList& faceToZoneID,
+    boolList& faceToFlip
+) const
+{
+    label readID = mesh_.faceZones().findZoneID(zoneName_);
+
+    if (readID == -1)
+    {
+        FatalErrorIn
+        (
+            "faceSelections::faceZoneSelection::select(labelList&) const"
+        )   << "Cannot find faceZone " << zoneName_ << nl << "Valid zones are "
+            << mesh_.faceZones().names()
+            << exit(FatalError);
+    }
+
+    const faceZone& fZone = mesh_.faceZones()[readID];
+
+    forAll(fZone, i)
+    {
+        label faceI = fZone[i];
+
+        if (faceToZoneID[faceI] == -1)
+        {
+            faceToZoneID[faceI] = zoneID;
+            faceToFlip[faceI] = fZone.flipMap()[i];
+        }
+        else if (faceToZoneID[faceI] != zoneID)
+        {
+            FatalErrorIn
+            (
+                "faceSelections::faceZoneSelection::select(labelList&) const"
+            )   << "Face " << faceI << " already in faceZone "
+                << faceToZoneID[faceI]
+                << exit(FatalError);
+        }
+    }
+
+    faceSelection::select(zoneID, faceToZoneID, faceToFlip);
+}
+
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/manipulation/createBaffles/faceSelection/faceZoneSelection.H b/applications/utilities/mesh/manipulation/createBaffles/faceSelection/faceZoneSelection.H
new file mode 100644
index 00000000000..1a2b15d3664
--- /dev/null
+++ b/applications/utilities/mesh/manipulation/createBaffles/faceSelection/faceZoneSelection.H
@@ -0,0 +1,114 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2012 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 <http://www.gnu.org/licenses/>.
+
+Class
+    Foam::faceSelections::faceZoneSelection
+
+Description
+    Deselect cells not reachable from 'inside' points
+
+SourceFiles
+    faceZoneSelection.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef faceZoneSelection_H
+#define faceZoneSelection_H
+
+#include "faceSelection.H"
+#include "pointField.H"
+#include "boolList.H"
+#include "volFields.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+class regionSplit;
+
+namespace faceSelections
+{
+
+/*---------------------------------------------------------------------------*\
+                     Class faceZoneSelection Declaration
+\*---------------------------------------------------------------------------*/
+
+class faceZoneSelection
+:
+    public faceSelection
+{
+    // Private data
+
+        //- Name of faceZone
+        const word zoneName_;
+
+
+   // Private Member Functions
+
+public:
+
+    //- Runtime type information
+    TypeName("faceZone");
+
+
+    // Constructors
+
+        //- Construct from dictionary
+        faceZoneSelection
+        (
+            const word& name,
+            const fvMesh& mesh,
+            const dictionary& dict
+        );
+
+        //- Clone
+        autoPtr<faceSelection> clone() const
+        {
+            notImplemented("autoPtr<faceSelection> clone() const");
+            return autoPtr<faceSelection>(NULL);
+        }
+
+
+    //- Destructor
+    virtual ~faceZoneSelection();
+
+
+    // Member Functions
+
+        //- Apply this selector
+        virtual void select(const label zoneID, labelList&, boolList&) const;
+
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace faceSelections
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/manipulation/createBaffles/faceSelection/searchableSurfaceSelection.C b/applications/utilities/mesh/manipulation/createBaffles/faceSelection/searchableSurfaceSelection.C
new file mode 100644
index 00000000000..1dbaaafaf84
--- /dev/null
+++ b/applications/utilities/mesh/manipulation/createBaffles/faceSelection/searchableSurfaceSelection.C
@@ -0,0 +1,172 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2012 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 <http://www.gnu.org/licenses/>.
+
+\*---------------------------------------------------------------------------*/
+
+#include "searchableSurfaceSelection.H"
+#include "addToRunTimeSelectionTable.H"
+#include "syncTools.H"
+#include "searchableSurface.H"
+#include "fvMesh.H"
+
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+namespace Foam
+{
+namespace faceSelections
+{
+    defineTypeNameAndDebug(searchableSurfaceSelection, 0);
+    addToRunTimeSelectionTable
+    (
+        faceSelection,
+        searchableSurfaceSelection,
+        dictionary
+    );
+}
+}
+
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::faceSelections::searchableSurfaceSelection::searchableSurfaceSelection
+(
+    const word& name,
+    const fvMesh& mesh,
+    const dictionary& dict
+)
+:
+    faceSelection(name, mesh, dict),
+    surfacePtr_
+    (
+        searchableSurface::New
+        (
+            word(dict.lookup("surface")),
+            mesh.objectRegistry::db(),
+            dict
+        )
+    )
+{}
+
+
+// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
+
+Foam::faceSelections::searchableSurfaceSelection::~searchableSurfaceSelection()
+{}
+
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+void Foam::faceSelections::searchableSurfaceSelection::select
+(
+    const label zoneID,
+    labelList& faceToZoneID,
+    boolList& faceToFlip
+) const
+{
+    // Get cell-cell centre vectors
+
+    pointField start(mesh_.nFaces());
+    pointField end(mesh_.nFaces());
+
+    // Internal faces
+    for (label faceI = 0; faceI < mesh_.nInternalFaces(); faceI++)
+    {
+        start[faceI] = mesh_.cellCentres()[mesh_.faceOwner()[faceI]];
+        end[faceI] = mesh_.cellCentres()[mesh_.faceNeighbour()[faceI]];
+    }
+
+    // Boundary faces
+    vectorField neighbourCellCentres;
+    syncTools::swapBoundaryCellList
+    (
+        mesh_,
+        mesh_.cellCentres(),
+        neighbourCellCentres
+    );
+
+    const polyBoundaryMesh& pbm = mesh_.boundaryMesh();
+
+    forAll(pbm, patchI)
+    {
+        const polyPatch& pp = pbm[patchI];
+
+        if (pp.coupled())
+        {
+            forAll(pp, i)
+            {
+                label faceI = pp.start()+i;
+                start[faceI] = mesh_.cellCentres()[mesh_.faceOwner()[faceI]];
+                end[faceI] = neighbourCellCentres[faceI-mesh_.nInternalFaces()];
+            }
+        }
+        else
+        {
+            forAll(pp, i)
+            {
+                label faceI = pp.start()+i;
+                start[faceI] = mesh_.cellCentres()[mesh_.faceOwner()[faceI]];
+                end[faceI] = mesh_.faceCentres()[faceI];
+            }
+        }
+    }
+
+    List<pointIndexHit> hits;
+    surfacePtr_().findLine(start, end, hits);
+    pointField normals;
+    surfacePtr_().getNormal(hits, normals);
+
+    //- Note: do not select boundary faces.
+
+    for (label faceI = 0; faceI < mesh_.nInternalFaces(); faceI++)
+    {
+        if (hits[faceI].hit())
+        {
+            faceToZoneID[faceI] = zoneID;
+            vector d = end[faceI]-start[faceI];
+            faceToFlip[faceI] = ((normals[faceI] & d) < 0);
+        }
+    }
+    forAll(pbm, patchI)
+    {
+        const polyPatch& pp = pbm[patchI];
+
+        if (pp.coupled())
+        {
+            forAll(pp, i)
+            {
+                label faceI = pp.start()+i;
+                if (hits[faceI].hit())
+                {
+                    faceToZoneID[faceI] = zoneID;
+                    vector d = end[faceI]-start[faceI];
+                    faceToFlip[faceI] = ((normals[faceI] & d) < 0);
+                }
+            }
+        }
+    }
+
+    faceSelection::select(zoneID, faceToZoneID, faceToFlip);
+}
+
+
+// ************************************************************************* //
diff --git a/applications/utilities/mesh/manipulation/createBaffles/faceSelection/searchableSurfaceSelection.H b/applications/utilities/mesh/manipulation/createBaffles/faceSelection/searchableSurfaceSelection.H
new file mode 100644
index 00000000000..f9831325527
--- /dev/null
+++ b/applications/utilities/mesh/manipulation/createBaffles/faceSelection/searchableSurfaceSelection.H
@@ -0,0 +1,106 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2012 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 <http://www.gnu.org/licenses/>.
+
+Class
+    Foam::faceSelections::searchableSurfaceSelection
+
+Description
+    Selects all (internal or coupled) faces intersecting the searchableSurface.
+
+SourceFiles
+    searchableSurfaceSelection.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef searchableSurfaceSelection_H
+#define searchableSurfaceSelection_H
+
+#include "faceSelection.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+class searchableSurface;
+
+namespace faceSelections
+{
+
+/*---------------------------------------------------------------------------*\
+                     Class searchableSurfaceSelection Declaration
+\*---------------------------------------------------------------------------*/
+
+class searchableSurfaceSelection
+:
+    public faceSelection
+{
+    // Private data
+
+        autoPtr<searchableSurface> surfacePtr_;
+
+public:
+
+    //- Runtime type information
+    TypeName("searchableSurface");
+
+
+    // Constructors
+
+        //- Construct from dictionary
+        searchableSurfaceSelection
+        (
+            const word& name,
+            const fvMesh& mesh,
+            const dictionary& dict
+        );
+
+        //- Clone
+        autoPtr<faceSelection> clone() const
+        {
+            notImplemented("autoPtr<faceSelection> clone() const");
+            return autoPtr<faceSelection>(NULL);
+        }
+
+
+    //- Destructor
+    virtual ~searchableSurfaceSelection();
+
+
+    // Member Functions
+
+        virtual void select(const label zoneID, labelList&, boolList&) const;
+
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace faceSelections
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
-- 
GitLab