/*---------------------------------------------------------------------------*\ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2015 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 . \*---------------------------------------------------------------------------*/ #include "globalMeshData.H" #include "Time.H" #include "Pstream.H" #include "PstreamCombineReduceOps.H" #include "processorPolyPatch.H" #include "demandDrivenData.H" #include "globalPoints.H" #include "polyMesh.H" #include "mapDistribute.H" #include "labelIOList.H" #include "PackedList.H" #include "mergePoints.H" #include "matchPoints.H" #include "OFstream.H" #include "globalIndexAndTransform.H" // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // namespace Foam { defineTypeNameAndDebug(globalMeshData, 0); // Geometric matching tolerance. Factor of mesh bounding box. const scalar globalMeshData::matchTol_ = 1e-8; template<> class minEqOp { 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 * * * * * * * * * * * // // Collect processor patch addressing. 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(mesh_.boundaryMesh()[patchi])) { processorPatches_[nNeighbours] = patchi; processorPatchIndices_[patchi] = nNeighbours++; } } processorPatches_.setSize(nNeighbours); if (Pstream::parRun()) { PstreamBuffers pBufs(Pstream::nonBlocking); // Send indices of my processor patches to my neighbours forAll(processorPatches_, i) { label patchi = processorPatches_[i]; UOPstream toNeighbour ( refCast ( mesh_.boundaryMesh()[patchi] ).neighbProcNo(), pBufs ); toNeighbour << processorPatchIndices_[patchi]; } pBufs.finishedSends(); forAll(processorPatches_, i) { label patchi = processorPatches_[i]; UIPstream fromNeighbour ( refCast ( mesh_.boundaryMesh()[patchi] ).neighbProcNo(), pBufs ); fromNeighbour >> processorPatchNeighbours_[patchi]; } } } void Foam::globalMeshData::calcSharedPoints() const { if ( nGlobalPoints_ != -1 || sharedPointLabelsPtr_.valid() || sharedPointAddrPtr_.valid() ) { FatalErrorIn("globalMeshData::calcSharedPoints()") << "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; } } // Given information about locally used edges allocate global shared edges. void Foam::globalMeshData::countSharedEdges ( const EdgeMap& procSharedEdges, EdgeMap