diff --git a/src/parallel/reconstruct/faReconstruct/Make/files b/src/parallel/reconstruct/faReconstruct/Make/files index 4d7028d13c..c0f15e7ecd 100644 --- a/src/parallel/reconstruct/faReconstruct/Make/files +++ b/src/parallel/reconstruct/faReconstruct/Make/files @@ -1,4 +1,5 @@ processorFaMeshes.C faFieldReconstructor.C +faMeshReconstructor.C LIB = $(FOAM_LIBBIN)/libfaReconstruct diff --git a/src/parallel/reconstruct/faReconstruct/faMeshReconstructor.C b/src/parallel/reconstruct/faReconstruct/faMeshReconstructor.C new file mode 100644 index 0000000000..0f85a81d5e --- /dev/null +++ b/src/parallel/reconstruct/faReconstruct/faMeshReconstructor.C @@ -0,0 +1,637 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2021 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 . + +\*---------------------------------------------------------------------------*/ + +#include "faMeshReconstructor.H" +#include "globalIndex.H" +#include "globalMeshData.H" +#include "edgeHashes.H" +#include "Time.H" +#include "PstreamCombineReduceOps.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +int Foam::faMeshReconstructor::debug = 0; + + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +void Foam::faMeshReconstructor::calcAddressing +( + const labelUList& fvFaceProcAddr +) +{ + const globalIndex globalFaceNum(procMesh_.nFaces()); + + // ---------------------- + // boundaryProcAddressing + // + // Trivial since non-processor boundary ordering is identical + + const label nPatches = procMesh_.boundary().size(); + + faBoundaryProcAddr_ = identity(nPatches); + + // Mark processor patches + for + ( + label patchi = procMesh_.boundary().nNonProcessor(); + patchi < nPatches; + ++patchi + ) + { + faBoundaryProcAddr_[patchi] = -1; + } + + + // ------------------ + // faceProcAddressing + // + // Transcribe/rewrite based on finiteVolume faceProcAddressing + + faFaceProcAddr_ = procMesh_.faceLabels(); + + // From local faceLabels to proc values + for (label& facei : faFaceProcAddr_) + { + // Use finiteVolume info, ignoring face flips + facei = mag(fvFaceProcAddr[facei] - 1); + } + + + // Make global consistent. + // Starting at '0', without gaps in numbering etc. + // - the sorted order is the obvious solution + { + globalFaceNum.gather(faFaceProcAddr_, singlePatchFaceLabels_); + + labelList order(Foam::sortedOrder(singlePatchFaceLabels_)); + + singlePatchFaceLabels_ = labelList(singlePatchFaceLabels_, order); + + globalFaceNum.scatter(order, faFaceProcAddr_); + } + + // Broadcast the same information everywhere + Pstream::scatter(singlePatchFaceLabels_); + + + // ------------------ + // edgeProcAddressing + // + // This is more complicated. + + // Create a single (serial) patch of the finiteArea mesh without a + // corresponding volume mesh, otherwise it would be the same as + // reconstructPar on the volume mesh (big, slow, etc). + // + // Do manual point-merge and relabeling to avoid dependency on + // finiteVolume pointProcAddressing + + faPointProcAddr_.clear(); // Final size == procMesh_.nPoints() + + // 1. + // - Topological point merge of the area meshes + // - use the local patch faces and points + + // 2. + // - build a single (serial) patch of the finiteArea mesh only + // without any point support from the volume mesh + // - it may be possible to skip this step, but not obvious how + + // The collected faces are contiguous per processor, which gives us + // the possibility to easily identify their source by using the + // global face indexing (if needed). + // The ultimate face locations are handled with a separate ordering + // list. + + const uindirectPrimitivePatch& procPatch = procMesh_.patch(); + + + { + faceList singlePatchProcFaces; // [proc0faces, proc1faces ...] + labelList uniqueMeshPointLabels; + + // Local face points to compact merged point index + labelList pointToGlobal; + + autoPtr globalPointsPtr = + procMesh_.mesh().globalData().mergePoints + ( + procPatch.meshPoints(), + procPatch.meshPointMap(), // unused + pointToGlobal, + uniqueMeshPointLabels + ); + + // Gather faces, renumbered for the *merged* points + faceList tmpFaces(globalFaceNum.localSize()); + + forAll(tmpFaces, facei) + { + tmpFaces[facei] = + face(pointToGlobal, procPatch.localFaces()[facei]); + } + + globalFaceNum.gather + ( + tmpFaces, + singlePatchProcFaces, + UPstream::msgType(), + Pstream::commsTypes::scheduled + ); + + globalPointsPtr().gather + ( + UIndirectList + ( + procPatch.points(), // NB: mesh points (non-local) + uniqueMeshPointLabels + ), + singlePatchPoints_ + ); + + // Transcribe into final assembled order + singlePatchFaces_.resize(singlePatchProcFaces.size()); + + // Target face ordering + labelList singlePatchProcAddr; + globalFaceNum.gather(faFaceProcAddr_, singlePatchProcAddr); + + forAll(singlePatchProcAddr, facei) + { + const label targetFacei = singlePatchProcAddr[facei]; + singlePatchFaces_[targetFacei] = singlePatchProcFaces[facei]; + } + + // Use initial equivalent "global" (serial) patch + // to establish the correct point and face walking order + // + // - only meaningful on master + const primitivePatch initialPatch + ( + SubList(singlePatchFaces_), + singlePatchPoints_ + ); + + // Grab the faces/points in local point ordering + tmpFaces = initialPatch.localFaces(); + pointField tmpPoints(initialPatch.localPoints()); + + // The meshPointMap is contiguous, so flatten as linear list + /// Map