/*---------------------------------------------------------------------------*\ ========= | \\ / F ield | foam-extend: Open Source CFD \\ / O peration | Version: 3.2 \\ / A nd | Web: http://www.foam-extend.org \\/ M anipulation | For copyright notice see file Copyright ------------------------------------------------------------------------------- License This file is part of foam-extend. foam-extend 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. foam-extend 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 foam-extend. If not, see . \*---------------------------------------------------------------------------*/ #include "faMeshDecomposition.H" #include "foamTime.H" #include "dictionary.H" #include "labelIOList.H" #include "processorFaPatch.H" #include "faMesh.H" #include "OSspecific.H" #include "Map.H" #include "globalMeshData.H" // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // 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 ) ); // If faMesh's fvPatch is a part of the global face zones, faces of that // patch will be present on all processors. Because of that, looping // through faceProcAddressing will decompose global faMesh faces to the // very last processor regardless of where fvPatch is really decomposed. // Since global faces which do not belong to specific processor are // located at the end of the faceProcAddressing, cutting it at // i = owner.size() will correctly decompose faMesh faces. // Vanja Skuric, 2016-04-21 if (decompositionDict_.found("globalFaceZones")) { labelList faceProcAddressing ( labelIOList ( IOobject ( "faceProcAddressing", "constant", procMesh.meshSubDir, procMesh, IOobject::MUST_READ, IOobject::NO_WRITE ) ) ); const label ownerSize = ( labelIOList ( IOobject ( "owner", "constant", procMesh.meshSubDir, procMesh, IOobject::MUST_READ, IOobject::NO_WRITE ) ) ).size(); labelHashSet faceProcAddressingHash(ownerSize); for (int i = 0; i < ownerSize; ++i) { faceProcAddressingHash.insert(faceProcAddressing[i]); } forAll (faceLabels(), faceI) { if (faceProcAddressingHash.found(faceLabels()[faceI] + 1)) { faceToProc_[faceI] = procI; } } } else { 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; } // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // // from components faMeshDecomposition::faMeshDecomposition(const fvMesh& mesh) : faMesh(mesh), decompositionDict_ ( IOobject ( "decomposeParDict", time().system(), mesh, IOobject::MUST_READ, IOobject::NO_WRITE ) ), nProcs_(readInt(decompositionDict_.lookup("numberOfSubdomains"))), distributed_(false), faceToProc_(nFaces()), procFaceLabels_(nProcs_), procMeshEdgesMap_(nProcs_), procNInternalEdges_(nProcs_, 0), procPatchEdgeLabels_(nProcs_), procPatchPointAddressing_(nProcs_), procPatchEdgeAddressing_(nProcs_), procEdgeAddressing_(nProcs_), procFaceAddressing_(nProcs_), procBoundaryAddressing_(nProcs_), procPatchSize_(nProcs_), procPatchStartIndex_(nProcs_), procNeighbourProcessors_(nProcs_), procProcessorPatchSize_(nProcs_), procProcessorPatchStartIndex_(nProcs_), globallySharedPoints_(0), cyclicParallel_(false) { if (decompositionDict_.found("distributed")) { distributed_ = Switch(decompositionDict_.lookup("distributed")); } } // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // faMeshDecomposition::~faMeshDecomposition() {} // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // void faMeshDecomposition::decomposeMesh(const bool filterEmptyPatches) { // Decide which cell goes to which processor distributeFaces(); Info<< "\nDistributing faces to processors" << endl; // Memory management { List > 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 > 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 )(); } // create processor finite area mesh faMesh procMesh ( procFvMesh, procFaceLabels_[procI] ); const indirectPrimitivePatch& patch = this->patch(); const Map