void Foam::decompositionConstraints::singleProcessorFaceSetsConstraint::add
(
    const polyMesh& mesh,
    boolList& blockedFace,
    PtrList<labelList>& specifiedProcessorFaces,
    labelList& specifiedProcessor,
    List<labelPair>& explicitConnections
) const
{
    blockedFace.setSize(mesh.nFaces(), true);

    // Mark faces already in set
    labelList faceToSet(mesh.nFaces(), -1);
    forAll(specifiedProcessorFaces, setI)
    {
        const labelList& faceLabels = specifiedProcessorFaces[setI];
        forAll(faceLabels, i)
        {
            faceToSet[faceLabels[i]] = setI;
        }
    }


    forAll(setNameAndProcs_, setI)
    {
        //Info<< "Keeping all cells connected to faceSet "
        //    << setNameAndProcs_[setI].first()
        //    << " on processor " << setNameAndProcs_[setI].second() << endl;

        const label destProcI = setNameAndProcs_[setI].second();

        // Read faceSet
        const faceSet fz(mesh, setNameAndProcs_[setI].first());

        // Check that it does not overlap with existing specifiedProcessorFaces
        labelList nMatch(specifiedProcessorFaces.size(), 0);
        forAllConstIter(faceSet, fz, iter)
        {
            label setI = faceToSet[iter.key()];
            if (setI != -1)
            {
                nMatch[setI]++;
            }
        }


        // Only store if all faces are not yet in specifiedProcessorFaces
        // (on all processors)
        bool store = true;

        forAll(nMatch, setI)
        {
            if (nMatch[setI] == fz.size())
            {
                // full match
                store = false;
                break;
            }
            else if (nMatch[setI] > 0)
            {
                // partial match
                store = false;
                break;
            }
        }

        reduce(store, andOp<bool>());


        if (store)
        {
            specifiedProcessorFaces.append(new labelList(fz.sortedToc()));
            specifiedProcessor.append(destProcI);
        }
    }