void faMeshDecomposition::distributeFaces()
{
    Info<< "\nCalculating distribution of faces" << endl;

    cpuTime decompositionTime;

    for (label procI = 0; procI < nProcs(); procI++)
    {
        Time processorDb
        (
            Time::controlDictName,
            time().rootPath(),
            time().caseName()/fileName(word("processor") + Foam::name(procI))
        );

        fvMesh procMesh
        (
            IOobject
            (
                fvMesh::defaultRegion,
                processorDb.timeName(),
                processorDb
            )
        );

        labelHashSet faceProcAddressingHash
        (
            labelIOList
            (
                IOobject
                (
                    "faceProcAddressing",
                    "constant",
                    procMesh.meshSubDir,
                    procMesh,
                    IOobject::MUST_READ,
                    IOobject::NO_WRITE
                )
            )
        );

        forAll (faceLabels(), faceI)
        {
            if (faceProcAddressingHash.found(faceLabels()[faceI] + 1))
            {
                faceToProc_[faceI] = procI;
            }
        }
    }

    Info<< "\nFinished decomposition in "
        << decompositionTime.elapsedCpuTime()
        << " s" << endl;
}
tmp<scalarField> FaceSetValueExpressionDriver::makeFaceFlipField() const
{
    // inspired by the setsToZones-utility

    tmp<scalarField> result(
        new scalarField(faceSet_->size())
    );

    word setName(faceSet_->name() + "SlaveCells");
    const fvMesh &mesh=this->mesh();

    SetOrigin origin=INVALID;

    cellSet cells(
        mesh,
        setName,
        getSet<cellSet>(
            mesh,
            setName,
            origin
        )
    );
    assert(origin!=INVALID);

    List<label> faceLabels(faceSet_->toc());

    forAll(faceLabels, i)
    {
        label faceI = faceLabels[i];

        bool flip = false;

        if (mesh.isInternalFace(faceI))
        {
            if
                (
                    cells.found(mesh.faceOwner()[faceI])
                    && !cells.found(mesh.faceNeighbour()[faceI])
                )
            {
                flip = false;
            }
            else if
                (
                    !cells.found(mesh.faceOwner()[faceI])
                    && cells.found(mesh.faceNeighbour()[faceI])
                )
            {
                flip = true;
            }
            else
            {
                FatalErrorIn("tmp<scalarField> FaceSetValueExpressionDriver::makeFaceFlipField()")
                    << "One of owner or neighbour of internal face "
                        << faceI << " should be in cellSet " << cells.name()
                        << " to be able to determine orientation." << endl
                        << "Face:" << faceI
                        << " own:" << mesh.faceOwner()[faceI]
                        << " OwnInCellSet:"
                        << cells.found(mesh.faceOwner()[faceI])
                        << " nei:" << mesh.faceNeighbour()[faceI]
                        << " NeiInCellSet:"
                        << cells.found(mesh.faceNeighbour()[faceI])
                        << exit(FatalError);
            }
        }
        else
        {
            if (cells.found(mesh.faceOwner()[faceI]))
            {
                flip = false;
            }
            else
            {
                flip = true;
            }
        }

        result()[i]= (flip ? -1 : 1 );
    }
void faMeshDecomposition::decomposeMesh(const bool filterEmptyPatches)
{
    // Decide which cell goes to which processor
    distributeFaces();

    Info<< "\nDistributing faces to processors" << endl;

    // Memory management
    {
        List<SLList<label> > procFaceList(nProcs());

        forAll (faceToProc_, faceI)
        {
            if (faceToProc_[faceI] >= nProcs())
            {
                FatalErrorIn("Finite area mesh decomposition")
                    << "Impossible processor label " << faceToProc_[faceI]
                    << "for face " << faceI
                    << abort(FatalError);
            }
            else
            {
                procFaceList[faceToProc_[faceI]].append(faceI);
            }
        }

        // Convert linked lists into normal lists
        forAll (procFaceList, procI)
        {
            procFaceAddressing_[procI] = procFaceList[procI];
        }
    }


    // Find processor mesh faceLabels and ...

    for (label procI = 0; procI < nProcs(); procI++)
    {
        Time processorDb
        (
            Time::controlDictName,
            time().rootPath(),
            time().caseName()/fileName(word("processor") + Foam::name(procI))
        );

        fvMesh procFvMesh
        (
            IOobject
            (
                fvMesh::defaultRegion,
                processorDb.timeName(),
                processorDb
            )
        );

        labelIOList fvPointProcAddressing
        (
            IOobject
            (
                "pointProcAddressing",
                "constant",
                procFvMesh.meshSubDir,
                procFvMesh,
                IOobject::MUST_READ,
                IOobject::NO_WRITE
            )
        );

        HashTable<label, label, Hash<label> > fvFaceProcAddressingHash;

        {
            labelIOList fvFaceProcAddressing
            (
                IOobject
                (
                    "faceProcAddressing",
                    "constant",
                    procFvMesh.meshSubDir,
                    procFvMesh,
                    IOobject::MUST_READ,
                    IOobject::NO_WRITE
                )
            );

            forAll(fvFaceProcAddressing, faceI)
            {
                 fvFaceProcAddressingHash.insert
                 (
                     fvFaceProcAddressing[faceI], faceI
                 );
            }
        };

        const labelList& curProcFaceAddressing = procFaceAddressing_[procI];

        labelList& curFaceLabels = procFaceLabels_[procI];

        curFaceLabels = labelList(curProcFaceAddressing.size(), -1);

        forAll(curProcFaceAddressing, faceI)
        {
            curFaceLabels[faceI] =
                fvFaceProcAddressingHash.find
                (
                    faceLabels()[curProcFaceAddressing[faceI]] + 1
                )();
        }