void Foam::AMIInterpolation<SourcePatch, TargetPatch>::distributePatches
(
    const mapDistribute& map,
    const TargetPatch& pp,
    const globalIndex& gi,
    List<faceList>& faces,
    List<pointField>& points,
    List<labelList>& faceIDs
) const
{
    PstreamBuffers pBufs(Pstream::nonBlocking);

    for (label domain = 0; domain < Pstream::nProcs(); domain++)
    {
        const labelList& sendElems = map.subMap()[domain];

        if (domain != Pstream::myProcNo() && sendElems.size())
        {
            labelList globalElems(sendElems.size());
            forAll(sendElems, i)
            {
                globalElems[i] = gi.toGlobal(sendElems[i]);
            }

            faceList subFaces(UIndirectList<face>(pp, sendElems));
            primitivePatch subPatch
            (
                SubList<face>(subFaces, subFaces.size()),
                pp.points()
            );

            if (debug & 2)
            {
                Pout<< "distributePatches: to processor " << domain
                    << " sending faces " << subPatch.faceCentres() << endl;
            }

            UOPstream toDomain(domain, pBufs);
            toDomain
                << subPatch.localFaces() << subPatch.localPoints()
                << globalElems;
        }
Foam::autoPtr<Foam::Istream>
Foam::fileOperations::masterFileOperation::NewIFstream
(
    const fileName& filePath
) const
{
    if (Pstream::parRun())
    {
        // Insert logic of filePath. We assume that if a file is absolute
        // on the master it is absolute also on the slaves etc.

        fileNameList filePaths(Pstream::nProcs());
        filePaths[Pstream::myProcNo()] = filePath;
        Pstream::gatherList(filePaths);

        PstreamBuffers pBufs(Pstream::nonBlocking);

        if (Pstream::master())
        {
            const bool uniform = uniformFile(filePaths);

            if (uniform)
            {
                if (IFstream::debug)
                {
                    Pout<< "Opening global file " << filePath << endl;
                }

                // get length of file:
                off_t count(Foam::fileSize(filePath));

                std::ifstream is(filePath);

                if (IFstream::debug)
                {
                    Pout<< "From " << filePath
                        <<  " reading " << label(count) << " bytes" << endl;
                }
                List<char> buf(static_cast<label>(count));
                is.read(buf.begin(), count);

                for (label proci = 1; proci < Pstream::nProcs(); proci++)
                {
                    UOPstream os(proci, pBufs);
                    os.write(buf.begin(), count);
                }
            }
            else
            {
                for (label proci = 1; proci < Pstream::nProcs(); proci++)
                {
                    if (IFstream::debug)
                    {
                        Pout<< "For processor " << proci
                            << " opening " << filePaths[proci] << endl;
                    }

                    off_t count(Foam::fileSize(filePaths[proci]));

                    std::ifstream is(filePaths[proci]);

                    if (IFstream::debug)
                    {
                        Pout<< "From " << filePaths[proci]
                            <<  " reading " << label(count) << " bytes" << endl;
                    }
                    List<char> buf(static_cast<label>(count));
                    is.read(buf.begin(), count);

                    UOPstream os(proci, pBufs);
                    os.write(buf.begin(), count);
                }
            }
        }


        labelList recvSizes;
        pBufs.finishedSends(recvSizes);

        if (Pstream::master())
        {
            // Read myself
            return autoPtr<Istream>
            (
                new IFstream(filePaths[Pstream::masterNo()])
            );
        }
        else
        {
            if (IFstream::debug)
            {
                Pout<< "Reading " << filePath
                    << " from processor " << Pstream::masterNo()
                    << endl;
            }

            UIPstream is(Pstream::masterNo(), pBufs);
            string buf(recvSizes[Pstream::masterNo()], '\0');
            is.read(&buf[0], recvSizes[Pstream::masterNo()]);

            if (IFstream::debug)
            {
                Pout<< "Done reading " << buf.size() << " bytes" << endl;
            }

            // Note: IPstream is not an IStream so use a IStringStream to
            //       convert the buffer. Note that we construct with a string
            //       so it holds a copy of the buffer.
            return autoPtr<Istream>(new IStringStream(buf));
        }
    }
    else
    {
        // Read myself
        return autoPtr<Istream>(new IFstream(filePath));
    }
}
Foam::autoPtr<Foam::Istream>
Foam::fileOperations::masterFileOperation::readStream
(
    regIOobject& io,
    const fileName& fName
) const
{
    if (!fName.size())
    {
        FatalErrorInFunction
            << "empty file name" << exit(FatalError);
    }

    fileNameList filePaths(Pstream::nProcs());
    filePaths[Pstream::myProcNo()] = fName;
    Pstream::gatherList(filePaths);

    PstreamBuffers pBufs(Pstream::nonBlocking);

    autoPtr<Istream> isPtr;

    if (Pstream::master())
    {
        //const bool uniform = uniformFile(filePaths);

        autoPtr<IFstream> ifsPtr(new IFstream(fName));
        IFstream& is = ifsPtr();

        // Read header
        if (!io.readHeader(is))
        {
            FatalIOErrorInFunction(is)
                << "problem while reading header for object " << io.name()
                << exit(FatalIOError);
        }

        // Open master (steal from ifsPtr)
        isPtr.reset(ifsPtr.ptr());

        // Read slave files
        for (label proci = 1; proci < Pstream::nProcs(); proci++)
        {
            if (IFstream::debug)
            {
                Pout<< "For processor " << proci
                    << " opening " << filePaths[proci] << endl;
            }

            std::ifstream is(filePaths[proci]);
            // Get length of file
            is.seekg(0, ios_base::end);
            std::streamoff count = is.tellg();
            is.seekg(0, ios_base::beg);

            if (IFstream::debug)
            {
                Pout<< "From " << filePaths[proci]
                    <<  " reading " << label(count) << " bytes" << endl;
            }
            List<char> buf(static_cast<label>(count));
            is.read(buf.begin(), count);

            UOPstream os(proci, pBufs);
            os.write(buf.begin(), count);
        }
    }

    labelList recvSizes;
    pBufs.finishedSends(recvSizes);

    // isPtr will be valid on master. Else the information is in the
    // PstreamBuffers

    if (!isPtr.valid())
    {
        UIPstream is(Pstream::masterNo(), pBufs);
        string buf(recvSizes[Pstream::masterNo()], '\0');
        is.read(&buf[0], recvSizes[Pstream::masterNo()]);

        if (IFstream::debug)
        {
            Pout<< "Done reading " << buf.size() << " bytes" << endl;
        }
        isPtr.reset(new IStringStream(buf));

        if (!io.readHeader(isPtr()))
        {
            FatalIOErrorInFunction(isPtr())
                << "problem while reading header for object " << io.name()
                << exit(FatalIOError);
        }
    }
    return isPtr;
}