Skip to content
Snippets Groups Projects
globalMeshData.C 77.4 KiB
Newer Older
  • Learn to ignore specific revisions
  • /*---------------------------------------------------------------------------*\
      =========                 |
      \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
       \\    /   O peration     |
    
    OpenFOAM bot's avatar
    OpenFOAM bot committed
        \\  /    A nd           | www.openfoam.com
    
         \\/     M anipulation  |
    -------------------------------------------------------------------------------
    
    OpenFOAM bot's avatar
    OpenFOAM bot committed
        Copyright (C) 2011-2017 OpenFOAM Foundation
        Copyright (C) 2015-2019 OpenCFD Ltd.
    
    -------------------------------------------------------------------------------
    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 "globalMeshData.H"
    #include "Pstream.H"
    #include "PstreamCombineReduceOps.H"
    #include "processorPolyPatch.H"
    #include "globalPoints.H"
    
    #include "polyMesh.H"
    #include "mapDistribute.H"
    
    #include "labelIOList.H"
    #include "mergePoints.H"
    
    #include "globalIndexAndTransform.H"
    
    
    // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
    
    
    namespace Foam
    {
    defineTypeNameAndDebug(globalMeshData, 0);
    
    const scalar globalMeshData::matchTol_ = 1e-8;
    
    template<>
    class minEqOp<labelPair>
    {
    public:
        void operator()(labelPair& x, const labelPair& y) const
        {
            x[0] = min(x[0], y[0]);
            x[1] = min(x[1], y[1]);
        }
    };
    }
    
    
    
    // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
    
    void Foam::globalMeshData::initProcAddr()
    {
        processorPatchIndices_.setSize(mesh_.boundaryMesh().size());
        processorPatchIndices_ = -1;
    
        processorPatchNeighbours_.setSize(mesh_.boundaryMesh().size());
        processorPatchNeighbours_ = -1;
    
        // Construct processor patch indexing. processorPatchNeighbours_ only
        // set if running in parallel!
        processorPatches_.setSize(mesh_.boundaryMesh().size());
    
        label nNeighbours = 0;
    
    
        forAll(mesh_.boundaryMesh(), patchi)
    
        {
            if (isA<processorPolyPatch>(mesh_.boundaryMesh()[patchi]))
            {
                processorPatches_[nNeighbours] = patchi;
                processorPatchIndices_[patchi] = nNeighbours++;
            }
        }
        processorPatches_.setSize(nNeighbours);
    
    
        if (Pstream::parRun())
        {
    
            PstreamBuffers pBufs(Pstream::commsTypes::nonBlocking);
    
            // Send indices of my processor patches to my neighbours
    
            for (const label patchi : processorPatches_)
    
                UOPstream toNeighbour
    
                (
                    refCast<const processorPolyPatch>
                    (
                        mesh_.boundaryMesh()[patchi]
    
                    ).neighbProcNo(),
                    pBufs
    
                );
    
                toNeighbour << processorPatchIndices_[patchi];
            }
    
    
            pBufs.finishedSends();
    
    
            for (const label patchi : processorPatches_)
    
                UIPstream fromNeighbour
    
                (
                    refCast<const processorPolyPatch>
                    (
                        mesh_.boundaryMesh()[patchi]
    
                    ).neighbProcNo(),
                    pBufs
    
                fromNeighbour >> processorPatchNeighbours_[patchi];
            }
        }
    }
    
    
    
    void Foam::globalMeshData::calcSharedPoints() const
    {
        if
        (
            nGlobalPoints_ != -1
         || sharedPointLabelsPtr_.valid()
         || sharedPointAddrPtr_.valid()
        )
        {
    
                << "Shared point addressing already done" << abort(FatalError);
        }
    
        // Calculate all shared points (exclude points that are only
        // on two coupled patches). This does all the hard work.
        globalPoints parallelPoints(mesh_, false, true);
    
        // Count the number of master points
        label nMaster = 0;
        forAll(parallelPoints.pointPoints(), i)
        {
            const labelList& pPoints = parallelPoints.pointPoints()[i];
            const labelList& transPPoints =
                parallelPoints.transformedPointPoints()[i];
    
            if (pPoints.size()+transPPoints.size() > 0)
            {
                nMaster++;
            }
        }
    
        // Allocate global numbers
        globalIndex masterNumbering(nMaster);
    
        nGlobalPoints_ = masterNumbering.size();
    
    
        // Push master number to slaves
        // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        // 1. Fill master and slave slots
        nMaster = 0;
        labelList master(parallelPoints.map().constructSize(), -1);
        forAll(parallelPoints.pointPoints(), i)
        {
            const labelList& pPoints = parallelPoints.pointPoints()[i];
            const labelList& transPPoints =
                parallelPoints.transformedPointPoints()[i];
    
            if (pPoints.size()+transPPoints.size() > 0)
            {
                master[i] = masterNumbering.toGlobal(nMaster);
                forAll(pPoints, j)
                {
                    master[pPoints[j]] = master[i];
                }
                forAll(transPPoints, j)
                {
                    master[transPPoints[j]] = master[i];
                }
                nMaster++;
            }
        }
    
    
        // 2. Push slave slots back to local storage on originating processor
        // For all the four types of points:
        // - local master : already set
        // - local transformed slave point : the reverse transform at
        //   reverseDistribute will have copied it back to its originating local
        //   point
        // - remote untransformed slave point : sent back to originating processor
        // - remote transformed slave point : the reverse transform will
        //   copy it back into the remote slot which then gets sent back to
        //   originating processor
    
        parallelPoints.map().reverseDistribute
        (
            parallelPoints.map().constructSize(),
            master
        );
    
    
        // Collect all points that are a master or refer to a master.
        nMaster = 0;
        forAll(parallelPoints.pointPoints(), i)
        {
            if (master[i] != -1)
            {
                nMaster++;
            }
        }
    
        sharedPointLabelsPtr_.reset(new labelList(nMaster));
        labelList& sharedPointLabels = sharedPointLabelsPtr_();
        sharedPointAddrPtr_.reset(new labelList(nMaster));
        labelList& sharedPointAddr = sharedPointAddrPtr_();
        nMaster = 0;
    
        forAll(parallelPoints.pointPoints(), i)
        {
            if (master[i] != -1)
            {
                // I am master or slave
                sharedPointLabels[nMaster] = i;
                sharedPointAddr[nMaster] = master[i];
                nMaster++;
            }
        }
    
        if (debug)
        {
            Pout<< "globalMeshData : nGlobalPoints_:" << nGlobalPoints_ << nl
                << "globalMeshData : sharedPointLabels_:"
                << sharedPointLabelsPtr_().size() << nl
                << "globalMeshData : sharedPointAddr_:"
                << sharedPointAddrPtr_().size() << endl;
        }
    }
    
    
    
    void Foam::globalMeshData::countSharedEdges
    (
    
        const EdgeMap<labelList>& procSharedEdges,
        EdgeMap<label>& globalShared,
    
        label& sharedEdgeI
    )
    {
        // Count occurrences of procSharedEdges in global shared edges table.
    
        forAllConstIters(procSharedEdges, iter)
    
        {
            const edge& e = iter.key();
    
    
            auto globalFnd = globalShared.find(e);
    
            if (globalFnd.found())
            {
                if (globalFnd() == -1)
                {
    
                    // Second time occurrence of this edge.
    
                    // Assign proper edge label.
                    globalFnd() = sharedEdgeI++;
                }
            }
            else
    
            {
                // First time occurrence of this edge. Check how many we are adding.
                if (iter().size() == 1)
                {
                    // Only one edge. Mark with special value.
                    globalShared.insert(e, -1);
                }
                else
                {
                    // Edge used more than once (even by local shared edges alone)
                    // so allocate proper shared edge label.
                    globalShared.insert(e, sharedEdgeI++);
                }
            }
        }
    }
    
    
    void Foam::globalMeshData::calcSharedEdges() const
    {
    
        // Shared edges are shared between multiple processors. By their nature both
        // of their endpoints are shared points. (but not all edges using two shared
        // points are shared edges! There might e.g. be an edge between two
        // unrelated clusters of shared points)
    
    
        if
        (
            nGlobalEdges_ != -1
         || sharedEdgeLabelsPtr_.valid()
         || sharedEdgeAddrPtr_.valid()
        )
    
                << "Shared edge addressing already done" << abort(FatalError);
        }
    
    
        const labelList& sharedPtAddr = sharedPointAddr();
        const labelList& sharedPtLabels = sharedPointLabels();
    
        // Since don't want to construct pointEdges for whole mesh create
        // Map for all shared points.
        Map<label> meshToShared(2*sharedPtLabels.size());
        forAll(sharedPtLabels, i)
        {
            meshToShared.insert(sharedPtLabels[i], i);
        }
    
        // Find edges using shared points. Store correspondence to local edge
        // numbering. Note that multiple local edges can have the same shared
        // points! (for cyclics or separated processor patches)
    
        EdgeMap<labelList> localShared(2*sharedPtAddr.size());
    
    
        const edgeList& edges = mesh_.edges();
    
        forAll(edges, edgeI)
        {
            const edge& e = edges[edgeI];
    
    
            const auto e0Fnd = meshToShared.cfind(e[0]);
    
            if (e0Fnd.found())
    
                const auto e1Fnd = meshToShared.cfind(e[1]);
    
                if (e1Fnd.found())
    
                {
                    // Found edge which uses shared points. Probably shared.
    
                    // Construct the edge in shared points (or rather global indices
                    // of the shared points)
                    edge sharedEdge
                    (
                        sharedPtAddr[e0Fnd()],
                        sharedPtAddr[e1Fnd()]
                    );
    
    
                    auto iter = localShared.find(sharedEdge);
    
                    if (!iter.found())
    
                    {
                        // First occurrence of this point combination. Store.
                        localShared.insert(sharedEdge, labelList(1, edgeI));
                    }
                    else
                    {
                        // Add this edge to list of edge labels.
                        labelList& edgeLabels = iter();
    
    
                        const label sz = edgeLabels.size();
    
                        edgeLabels.setSize(sz+1);
                        edgeLabels[sz] = edgeI;
                    }
                }
            }
        }
    
    
        // Now we have a table on every processors which gives its edges which use
        // shared points. Send this all to the master and have it allocate
        // global edge numbers for it. But only allocate a global edge number for
        // edge if it is used more than once!
        // Note that we are now sending the whole localShared to the master whereas
        // we only need the local count (i.e. the number of times a global edge is
        // used). But then this only gets done once so not too bothered about the
        // extra global communication.
    
    
        EdgeMap<label> globalShared(nGlobalPoints());
    
    
        if (Pstream::master())
        {
            label sharedEdgeI = 0;
    
            // Merge my shared edges into the global list
            if (debug)
            {
                Pout<< "globalMeshData::calcSharedEdges : Merging in from proc0 : "
                    << localShared.size() << endl;
            }
            countSharedEdges(localShared, globalShared, sharedEdgeI);
    
            // Receive data from slaves and insert
            if (Pstream::parRun())
            {
                for
                (
                    int slave=Pstream::firstSlave();
                    slave<=Pstream::lastSlave();
                    slave++
                )
                {
                    // Receive the edges using shared points from the slave.
    
                    IPstream fromSlave(Pstream::commsTypes::blocking, slave);
    
                    EdgeMap<labelList> procSharedEdges(fromSlave);
    
    
                    if (debug)
                    {
                        Pout<< "globalMeshData::calcSharedEdges : "
                            << "Merging in from proc"
                            << Foam::name(slave) << " : " << procSharedEdges.size()
                            << endl;
                    }
                    countSharedEdges(procSharedEdges, globalShared, sharedEdgeI);
                }
            }
    
            // Now our globalShared should have some edges with -1 as edge label
            // These were only used once so are not proper shared edges.
            // Remove them.
            {
    
                EdgeMap<label> oldSharedEdges(globalShared);
    
                forAllConstIters(oldSharedEdges, iter)
    
                {
                    if (iter() != -1)
                    {
                        globalShared.insert(iter.key(), iter());
                    }
                }
                if (debug)
                {
                    Pout<< "globalMeshData::calcSharedEdges : Filtered "
                        << oldSharedEdges.size()
                        << " down to " << globalShared.size() << endl;
                }
            }
    
    
            // Send back to slaves.
            if (Pstream::parRun())
            {
                for
                (
                    int slave=Pstream::firstSlave();
                    slave<=Pstream::lastSlave();
                    slave++
                )
                {
                    // Receive the edges using shared points from the slave.
    
                    OPstream toSlave(Pstream::commsTypes::blocking, slave);
    
                    toSlave << globalShared;
                }
            }
        }
        else
        {
            // Send local edges to master
            {
    
                OPstream toMaster
                (
                    Pstream::commsTypes::blocking,
                    Pstream::masterNo()
                );
    
                toMaster << localShared;
            }
            // Receive merged edges from master.
            {
    
                IPstream fromMaster
                (
                    Pstream::commsTypes::blocking,
                    Pstream::masterNo()
                );
    
                fromMaster >> globalShared;
            }
        }
    
        // Now use the global shared edges list (globalShared) to classify my local
        // ones (localShared)
    
        nGlobalEdges_ = globalShared.size();
    
        DynamicList<label> dynSharedEdgeLabels(globalShared.size());
        DynamicList<label> dynSharedEdgeAddr(globalShared.size());
    
    
        forAllConstIters(localShared, iter)
    
        {
            const edge& e = iter.key();
    
    
            const auto edgeFnd = globalShared.cfind(e);
    
            if (edgeFnd.found())
    
            {
                // My local edge is indeed a shared one. Go through all local edge
                // labels with this point combination.
                const labelList& edgeLabels = iter();
    
    
                for (const label edgei : edgeLabels)
    
                {
                    // Store label of local mesh edge
    
                    dynSharedEdgeLabels.append(edgei);
    
    
                    // Store label of shared edge
                    dynSharedEdgeAddr.append(edgeFnd());
                }
            }
        }
    
        sharedEdgeLabelsPtr_.reset(new labelList());
        labelList& sharedEdgeLabels = sharedEdgeLabelsPtr_();
    
        sharedEdgeLabels.transfer(dynSharedEdgeLabels);
    
    
        sharedEdgeAddrPtr_.reset(new labelList());
        labelList& sharedEdgeAddr = sharedEdgeAddrPtr_();
    
        sharedEdgeAddr.transfer(dynSharedEdgeAddr);
    
        if (debug)
        {
            Pout<< "globalMeshData : nGlobalEdges_:" << nGlobalEdges_ << nl
                << "globalMeshData : sharedEdgeLabels:" << sharedEdgeLabels.size()
                << nl
                << "globalMeshData : sharedEdgeAddr:" << sharedEdgeAddr.size()
                << endl;
        }
    }
    
    
    
    void Foam::globalMeshData::calcGlobalPointSlaves() const
    
            Pout<< "globalMeshData::calcGlobalPointSlaves() :"
                << " calculating coupled master to slave point addressing."
                << endl;
    
        // Calculate connected points for master points.
        globalPoints globalData(mesh_, coupledPatch(), true, true);
    
                std::move(globalData.pointPoints())
    
        globalPointTransformedSlavesPtr_.reset
    
                std::move(globalData.transformedPointPoints())
    
                std::move(globalData.map())
    
    void Foam::globalMeshData::calcPointConnectivity
    (
        List<labelPairList>& allPointConnectivity
    ) const
    
        const globalIndexAndTransform& transforms = globalTransforms();
        const labelListList& slaves = globalPointSlaves();
        const labelListList& transformedSlaves = globalPointTransformedSlaves();
    
    
        // Create field with my local data
        labelPairList myData(globalPointSlavesMap().constructSize());
    
                transforms.nullTransformIndex()
            );
    
        globalPointSlavesMap().distribute(myData);
    
        // String of connected points with their transform
        allPointConnectivity.setSize(globalPointSlavesMap().constructSize());
    
        allPointConnectivity = labelPairList(0);
    
        // Pass1: do the master points since these also update local slaves
        //        (e.g. from local cyclics)
    
        {
            // Reconstruct string of connected points
    
            const labelList& pSlaves = slaves[pointi];
            const labelList& pTransformSlaves = transformedSlaves[pointi];
    
            if (pSlaves.size()+pTransformSlaves.size())
    
                labelPairList& pConnectivity = allPointConnectivity[pointi];
    
                pConnectivity.setSize(1+pSlaves.size()+pTransformSlaves.size());
                label connI = 0;
    
                // Add myself
    
                pConnectivity[connI++] = myData[pointi];
    
                // Add untransformed points
                forAll(pSlaves, i)
                {
                    pConnectivity[connI++] = myData[pSlaves[i]];
                }
                // Add transformed points.
                forAll(pTransformSlaves, i)
                {
                    // Get transform from index
                    label transformI = globalPointSlavesMap().whichTransform
                    (
                        pTransformSlaves[i]
                    );
                    // Add transform to connectivity
                    const labelPair& n = myData[pTransformSlaves[i]];
    
                    label proci = transforms.processor(n);
                    label index = transforms.index(n);
                    pConnectivity[connI++] = transforms.encode
    
                    (
                        proci,
                        index,
                        transformI
                    );
                }
    
                // Put back in slots
                forAll(pSlaves, i)
                {
                    allPointConnectivity[pSlaves[i]] = pConnectivity;
                }
                forAll(pTransformSlaves, i)
                {
                    allPointConnectivity[pTransformSlaves[i]] = pConnectivity;
                }
    
        }
    
    
        // Pass2: see if anything is still unset (should not be the case)
    
            labelPairList& pConnectivity = allPointConnectivity[pointi];
    
                pConnectivity.setSize(1, myData[pointi]);
    
        globalPointSlavesMap().reverseDistribute
        (
    
    void Foam::globalMeshData::calcGlobalPointEdges
    (
        labelListList& globalPointEdges,
        List<labelPairList>& globalPointPoints
    ) const
    {
        const edgeList& edges = coupledPatch().edges();
    
        const labelListList& pointEdges = coupledPatch().pointEdges();
    
        const globalIndex& globalEdgeNumbers = globalEdgeNumbering();
    
        const labelListList& slaves = globalPointSlaves();
        const labelListList& transformedSlaves = globalPointTransformedSlaves();
    
        const globalIndexAndTransform& transforms = globalTransforms();
    
    
    
        // Create local version
        globalPointEdges.setSize(globalPointSlavesMap().constructSize());
        globalPointPoints.setSize(globalPointSlavesMap().constructSize());
    
            const labelList& pEdges = pointEdges[pointi];
    
            globalPointEdges[pointi] = globalEdgeNumbers.toGlobal(pEdges);
    
            labelPairList& globalPPoints = globalPointPoints[pointi];
    
            globalPPoints.setSize(pEdges.size());
            forAll(pEdges, i)
            {
    
                label otherPointi = edges[pEdges[i]].otherVertex(pointi);
    
        // Pull slave data to master. Dummy transform.
        globalPointSlavesMap().distribute(globalPointEdges);
    
        globalPointSlavesMap().distribute(globalPointPoints);
        // Add all pointEdges
    
            const labelList& pSlaves = slaves[pointi];
            const labelList& pTransformSlaves = transformedSlaves[pointi];
    
            label n = 0;
            forAll(pSlaves, i)
            {
                n += globalPointEdges[pSlaves[i]].size();
            }
            forAll(pTransformSlaves, i)
            {
                n += globalPointEdges[pTransformSlaves[i]].size();
            }
    
            // Add all the point edges of the slaves to those of the (master) point
            {
    
                labelList& globalPEdges = globalPointEdges[pointi];
    
                label sz = globalPEdges.size();
                globalPEdges.setSize(sz+n);
                forAll(pSlaves, i)
                {
                    const labelList& otherData = globalPointEdges[pSlaves[i]];
                    forAll(otherData, j)
                    {
                        globalPEdges[sz++] = otherData[j];
                    }
                }
                forAll(pTransformSlaves, i)
                {
                    const labelList& otherData =
                        globalPointEdges[pTransformSlaves[i]];
                    forAll(otherData, j)
                    {
                        globalPEdges[sz++] = otherData[j];
                    }
                }
    
                // Put back in slots
                forAll(pSlaves, i)
                {
                    globalPointEdges[pSlaves[i]] = globalPEdges;
                }
                forAll(pTransformSlaves, i)
                {
                    globalPointEdges[pTransformSlaves[i]] = globalPEdges;
                }
            }
    
            // Same for corresponding pointPoints
    
                labelPairList& globalPPoints = globalPointPoints[pointi];
    
                label sz = globalPPoints.size();
                globalPPoints.setSize(sz + n);
    
                // Add untransformed points
                forAll(pSlaves, i)
    
                    const labelPairList& otherData = globalPointPoints[pSlaves[i]];
                    forAll(otherData, j)
    
                        globalPPoints[sz++] = otherData[j];
    
                // Add transformed points.
                forAll(pTransformSlaves, i)
    
                    // Get transform from index
                    label transformI = globalPointSlavesMap().whichTransform
                    (
                        pTransformSlaves[i]
                    );
    
                    const labelPairList& otherData =
                        globalPointPoints[pTransformSlaves[i]];
                    forAll(otherData, j)
                    {
                        // Add transform to connectivity
                        const labelPair& n = otherData[j];
    
                        label proci = transforms.processor(n);
                        label index = transforms.index(n);
                        globalPPoints[sz++] = transforms.encode
    
    
                // Put back in slots
                forAll(pSlaves, i)
                {
                    globalPointPoints[pSlaves[i]] = globalPPoints;
                }
                forAll(pTransformSlaves, i)
                {
                    globalPointPoints[pTransformSlaves[i]] = globalPPoints;
                }
    
        }
        // Push back
        globalPointSlavesMap().reverseDistribute
        (
    
            globalPointEdges
        );
        // Push back
        globalPointSlavesMap().reverseDistribute
        (
    
    Foam::label Foam::globalMeshData::findTransform
    (
        const labelPairList& info,
        const labelPair& remotePoint,
        const label localPoint
    ) const
    {
    
        const globalIndexAndTransform& transforms = globalTransforms();
    
        const label remoteProci = transforms.processor(remotePoint);
        const label remoteIndex = transforms.index(remotePoint);
    
    
        label remoteTransformI = -1;
        label localTransformI = -1;
        forAll(info, i)
        {
    
            label proci = transforms.processor(info[i]);
            label pointi = transforms.index(info[i]);
            label transformI = transforms.transformIndex(info[i]);
    
            if (proci == Pstream::myProcNo() && pointi == localPoint)
    
            {
                localTransformI = transformI;
                //Pout<< "For local :" << localPoint
                //    << " found transform:" << localTransformI
                //    << endl;
            }
    
            if (proci == remoteProci && pointi == remoteIndex)
    
                remoteTransformI = transformI;
                //Pout<< "For remote:" << remotePoint
                //    << " found transform:" << remoteTransformI
                //    << " at index:" << i
                //    << endl;
            }
        }
    
        if (remoteTransformI == -1 || localTransformI == -1)
        {
    
                << "Problem. Cannot find " << remotePoint
    
                << " or " << localPoint  << " "
                << coupledPatch().localPoints()[localPoint]
                << " in " << info
    
                << endl
                << "remoteTransformI:" << remoteTransformI << endl
                << "localTransformI:" << localTransformI
                << abort(FatalError);
        }
    
        (
            remoteTransformI,
            localTransformI
        );
    }
    
    
    void Foam::globalMeshData::calcGlobalEdgeSlaves() const
    {
        if (debug)
        {
            Pout<< "globalMeshData::calcGlobalEdgeSlaves() :"
                << " calculating coupled master to slave edge addressing." << endl;
        }
    
        const edgeList& edges = coupledPatch().edges();
        const globalIndex& globalEdgeNumbers = globalEdgeNumbering();
    
        const globalIndexAndTransform& transforms = globalTransforms();
    
    
    
        // The whole problem with deducting edge-connectivity from
    
    Andrew Heather's avatar
    Andrew Heather committed
        // point-connectivity is that one of the endpoints might be
    
        // a local master but the other endpoint might not. So we first
        // need to make sure that all points know about connectivity and
        // the transformations.
    
    
    
    laurence's avatar
    laurence committed
        // 1. collect point connectivity - basically recreating globalPoints output.
    
        // All points will now have a string of coupled points. The transforms are
    
        // in respect to the master.
        List<labelPairList> allPointConnectivity;
        calcPointConnectivity(allPointConnectivity);
    
    
        // 2. Get all pointEdges and pointPoints
        // Coupled point to global coupled edges and corresponding endpoint.
        labelListList globalPointEdges;
        List<labelPairList> globalPointPoints;
        calcGlobalPointEdges(globalPointEdges, globalPointPoints);
    
    
        // 3. Now all points have
        //      - all the connected points with original transform
        //      - all the connected global edges
    
        // Now all we need to do is go through all the edges and check
        // both endpoints. If there is a edge between the two which is
        // produced by transforming both points in the same way it is a shared
        // edge.
    
        // Collect strings of connected edges.
        List<labelPairList> allEdgeConnectivity(edges.size());
    
        forAll(edges, edgeI)
        {
            const edge& e = edges[edgeI];
            const labelList& pEdges0 = globalPointEdges[e[0]];
            const labelPairList& pPoints0 = globalPointPoints[e[0]];
            const labelList& pEdges1 = globalPointEdges[e[1]];
            const labelPairList& pPoints1 = globalPointPoints[e[1]];
    
            // Most edges will be size 2
            DynamicList<labelPair> eEdges(2);
            // Append myself.
            eEdges.append
            (
    
                (
                    Pstream::myProcNo(),
                    edgeI,
    
                )
            );
    
            forAll(pEdges0, i)
            {
                forAll(pEdges1, j)
    
                    if
                    (
                        pEdges0[i] == pEdges1[j]
                     && pEdges0[i] != globalEdgeNumbers.toGlobal(edgeI)
                    )
    
                        // Found a shared edge. Now check if the endpoints
                        // go through the same transformation.
                        // Local: e[0]    remote:pPoints1[j]
                        // Local: e[1]    remote:pPoints0[i]
    
    
                        // Find difference in transforms to go from point on remote
                        // edge (pPoints1[j]) to this point.
    
                        label transform0 = findTransform
    
                            allPointConnectivity[e[0]],
                            pPoints1[j],
                            e[0]
                        );
                        label transform1 = findTransform
                        (
                            allPointConnectivity[e[1]],
                            pPoints0[i],
                            e[1]
    
                        if (transform0 == transform1)
                        {
    
                            label proci = globalEdgeNumbers.whichProcID(pEdges0[i]);
    
                                    proci,
                                    globalEdgeNumbers.toLocal(proci, pEdges0[i]),