diff --git a/applications/utilities/preProcessing/mapFieldsPar/mapFieldsPar.C b/applications/utilities/preProcessing/mapFieldsPar/mapFieldsPar.C index 1d021b5280d82e72cdf4593bb6c458e924919ac7..194b08242c70a2379cc0f673d5690f041504c192 100644 --- a/applications/utilities/preProcessing/mapFieldsPar/mapFieldsPar.C +++ b/applications/utilities/preProcessing/mapFieldsPar/mapFieldsPar.C @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation - \\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd. + \\/ M anipulation | Copyright (C) 2015-2018 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -46,6 +46,7 @@ void mapConsistentMesh const fvMesh& meshTarget, const word& mapMethod, const word& AMIMapMethod, + const word& procMapMethod, const bool subtract, const wordHashSet& selectedFields, const bool noLagrangian @@ -54,7 +55,14 @@ void mapConsistentMesh Info<< nl << "Consistently creating and mapping fields for time " << meshSource.time().timeName() << nl << endl; - meshToMesh interp(meshSource, meshTarget, mapMethod, AMIMapMethod); + meshToMesh interp + ( + meshSource, + meshTarget, + mapMethod, + AMIMapMethod, + meshToMesh::procMapMethodNames_[procMapMethod] + ); if (subtract) { @@ -85,6 +93,7 @@ void mapSubMesh const wordList& cuttingPatches, const word& mapMethod, const word& AMIMapMethod, + const word& procMapMethod, const bool subtract, const wordHashSet& selectedFields, const bool noLagrangian @@ -100,7 +109,8 @@ void mapSubMesh mapMethod, AMIMapMethod, patchMap, - cuttingPatches + cuttingPatches, + meshToMesh::procMapMethodNames_[procMapMethod] ); if (subtract) @@ -171,6 +181,12 @@ int main(int argc, char *argv[]) "word", "specify the patch mapping method (direct|mapNearest|faceAreaWeight)" ); + argList::addOption + ( + "procMapMethod", + "word", + "specify the processor distribution map method (AABB|LOD)" + ); argList::addBoolOption ( "subtract", @@ -217,7 +233,7 @@ int main(int argc, char *argv[]) word mapMethod = meshToMesh::interpolationMethodNames_ [ - meshToMesh::imCellVolumeWeight + meshToMesh::interpolationMethod::imCellVolumeWeight ]; if (args.readIfPresent("mapMethod", mapMethod)) @@ -225,7 +241,6 @@ int main(int argc, char *argv[]) Info<< "Mapping method: " << mapMethod << endl; } - word patchMapMethod; if (meshToMesh::interpolationMethodNames_.found(mapMethod)) { @@ -233,12 +248,25 @@ int main(int argc, char *argv[]) meshToMesh::interpolationMethod method = meshToMesh::interpolationMethodNames_[mapMethod]; - patchMapMethod = AMIPatchToPatchInterpolation::interpolationMethodNames_ + patchMapMethod = + AMIPatchToPatchInterpolation::interpolationMethodNames_ + [ + meshToMesh::interpolationMethodAMI(method) + ]; + } + + word procMapMethod = + meshToMesh::procMapMethodNames_ [ - meshToMesh::interpolationMethodAMI(method) + meshToMesh::procMapMethod::pmAABB ]; + + if (args.readIfPresent("procMapMethod", procMapMethod)) + { + Info<< "Processor map method: " << procMapMethod << endl; } + // Optionally override if (args.readIfPresent("patchMapMethod", patchMapMethod)) { @@ -325,6 +353,7 @@ int main(int argc, char *argv[]) meshTarget, mapMethod, patchMapMethod, + procMapMethod, subtract, selectedFields, noLagrangian @@ -340,12 +369,15 @@ int main(int argc, char *argv[]) cuttingPatches, mapMethod, patchMapMethod, + procMapMethod, subtract, selectedFields, noLagrangian ); } + runTimeSource.printExecutionTime(Info); + Info<< "\nEnd\n" << endl; return 0; diff --git a/src/fvOptions/interRegionOption/interRegionOption.C b/src/fvOptions/interRegionOption/interRegionOption.C index 32a3f88564cd6f5de3c481231a123569dd51bdd6..bf81ccf38354254e39ce124783e7929be9906bbf 100644 --- a/src/fvOptions/interRegionOption/interRegionOption.C +++ b/src/fvOptions/interRegionOption/interRegionOption.C @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2018 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -65,10 +65,17 @@ void Foam::fv::interRegionOption::setMapper() ( mesh_, nbrMesh, - meshToMesh::interpolationMethodNames_.lookup + meshToMesh::interpolationMethodNames_.lookupOrDefault ( "interpolationMethod", - coeffs_ + coeffs_, + meshToMesh::interpolationMethod::imCellVolumeWeight + ), + meshToMesh::procMapMethodNames_.lookupOrDefault + ( + "procMapMethod", + coeffs_, + meshToMesh::procMapMethod::pmAABB ), false // not interpolating patches ) diff --git a/src/meshTools/Make/files b/src/meshTools/Make/files index 45f839d1a0defcd51550b297c566c4d808a09b1f..56dc286f3a9cb384b481beb518e59699a10a006c 100644 --- a/src/meshTools/Make/files +++ b/src/meshTools/Make/files @@ -231,6 +231,11 @@ triSurface/triSurfaceTools/pointToPointPlanarInterpolation.C twoDPointCorrector/twoDPointCorrector.C +processorLOD/processorLOD/processorLOD.C +processorLOD/box/box.C +processorLOD/cellBox/cellBox.C +processorLOD/faceBox/faceBox.C + AMI=AMIInterpolation $(AMI)/AMIInterpolation/AMIInterpolationName.C $(AMI)/AMIInterpolation/AMIPatchToPatchInterpolation.C diff --git a/src/meshTools/processorLOD/box/box.C b/src/meshTools/processorLOD/box/box.C new file mode 100644 index 0000000000000000000000000000000000000000..f176ab0fd068adb71241bdd0e64c2201c9138ee1 --- /dev/null +++ b/src/meshTools/processorLOD/box/box.C @@ -0,0 +1,635 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2017 OpenCFD Ltd. + \\/ 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 <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "box.H" +#include "mapDistribute.H" +#include "OFstream.H" +#include "meshTools.H" + +const Foam::label Foam::processorLODs::box::DROP = 0; +const Foam::label Foam::processorLODs::box::REFINE = 1; +const Foam::label Foam::processorLODs::box::FIXED = 2; +const Foam::label Foam::processorLODs::box::nStartUpIter = 2; + +namespace Foam +{ +namespace processorLODs +{ + defineTypeNameAndDebug(box, 0); +} +} + +// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * // + +void Foam::processorLODs::box::writeBoxes +( + const List<DynamicList<treeBoundBox>>& fixedBoxes, + const label iter +) const +{ + static label time = 0; + + OFstream os + ( + "processor" + Foam::name(Pstream::myProcNo()) + + "_time" + Foam::name(time) + + "_iter" + Foam::name(iter) + ".obj" + ); + + label verti = 0; + for (label proci = 0; proci < Pstream::nProcs(); ++proci) + { + if (proci == Pstream::myProcNo()) + { + continue; + } + + const DynamicList<treeBoundBox>& procBoxes = fixedBoxes[proci]; + forAll(procBoxes, boxi) + { + const treeBoundBox& bb = procBoxes[boxi]; + + // Write the points + const pointField pts(bb.points()); + for (const point& p : pts) + { + meshTools::writeOBJ(os, p); + } + + // Write the box faces + for (const face& f : bb.faces) + { + os << 'f'; + for (const label fpi : f) + { + os << ' ' << fpi + verti + 1; + } + os << nl; + } + verti += pts.size(); + } + } + + ++time; +} + + +void Foam::processorLODs::box::setRefineFlags +( + const label refineIter, + const label nTgtObjects, + List<labelHashSet>& fixedSendElems, + List<List<labelList>>& localTgtElems, + List<labelList>& refineFlags, + labelList& nElems +) const +{ + PstreamBuffers pBufs(Pstream::commsTypes::nonBlocking); + + // Identify src boxes that can be refined and send to all remote procs + for (label proci = 0; proci < Pstream::nProcs(); ++proci) + { + if (proci != Pstream::myProcNo()) + { + UOPstream toProc(proci, pBufs); + toProc << nObjectsOfType_ << boxes_[proci] << newToOld_[proci]; + } + } + + pBufs.finishedSends(); + + // Test each remote src bb with local tgt objects to identify which remote + // src boxes can/should be refined + for (label proci = 0; proci < Pstream::nProcs(); ++proci) + { + if (proci == Pstream::myProcNo()) + { + // Not refining boxes I send to myself - will be sending all local + // elements + continue; + } + + // Receive the subset of changing src bound boxes for proci + UIPstream fromProc(proci, pBufs); + const label nObjects = readLabel(fromProc); + List<treeBoundBox> remoteSrcBoxes(fromProc); + const List<label> newToOld(fromProc); + + if (remoteSrcBoxes.empty()) + { + continue; + } + + + labelList& procRefineFlags = refineFlags[proci]; + procRefineFlags.setSize(remoteSrcBoxes.size(), FIXED); + + if (scalar(nTgtObjects)/scalar(nObjects) < 0.1) + { + // Sending less than 10% of objects of this type + // - shortcut by sending all + fixedSendElems[proci].insert(identity(nTgtObjects)); + nElems[proci] = nTgtObjects; + + continue; + } + + label nElem = 0; + List<labelList>& localProcTgtElems = localTgtElems[proci]; + List<labelList> newLocalProcTgtElems(remoteSrcBoxes.size()); + + forAll(remoteSrcBoxes, srcBoxi) + { + const treeBoundBox& remSrcBb = remoteSrcBoxes[srcBoxi]; + DynamicList<label> selectedElems(maxObjectsPerLeaf_); + + if (refineIter > nStartUpIter) + { + // Iterate over cached subset of tgt elements + const label oldBoxi = newToOld[srcBoxi]; + const labelList& tgtBoxElems = localProcTgtElems[oldBoxi]; + + for (const label tgtObji : tgtBoxElems) + { + if (calcTgtBox(tgtObji).overlaps(remSrcBb)) + { + selectedElems.append(tgtObji); + } + } + } + else + { + // Iterating over all target elements + for (label tgtObji = 0; tgtObji < nTgtObjects; ++tgtObji) + { + if (calcTgtBox(tgtObji).overlaps(remSrcBb)) + { + selectedElems.append(tgtObji); + } + } + } + + nElem += selectedElems.size(); + + if + ( + proci == Pstream::myProcNo() + || selectedElems.size() < maxObjectsPerLeaf_ + ) + { + procRefineFlags[srcBoxi] = FIXED; + fixedSendElems[proci].insert(selectedElems); + } + else + { + procRefineFlags[srcBoxi] = REFINE; + if (refineIter >= nStartUpIter) + { + newLocalProcTgtElems[srcBoxi].transfer(selectedElems); + } + } + } + + localProcTgtElems.transfer(newLocalProcTgtElems); + nElems[proci] = nElem; + } +} + + +void Foam::processorLODs::box::refineBox +( + const label boxi, + const label refineIter, + const label nSrcElem, + const treeBoundBox& origBox, + DynamicList<treeBoundBox>& procBoxes, + DynamicList<labelList>& procBoxElems, + DynamicList<label>& procNewToOld +) const +{ + // Create the new boxes + + if (refineIter == nStartUpIter) + { + // Start caching the addressing + for (direction octant = 0; octant < 8; ++octant) + { + const treeBoundBox subBb(origBox.subBbox(octant)); + + // Identify the src elements for each box + DynamicList<label> newElems(nSrcElem/2); + + for (label srcElemi = 0; srcElemi < nSrcElem; ++srcElemi) + { + if (subBb.overlaps(calcSrcBox(srcElemi))) + { + newElems.append(srcElemi); + } + } + + if (newElems.size()) + { + procBoxes.append(subBb); + procBoxElems.append(newElems); + procNewToOld.append(boxi); + } + } + } + else + { + for (direction octant = 0; octant < 8; ++octant) + { + const treeBoundBox subBb(origBox.subBbox(octant)); + + for (label srcElemi = 0; srcElemi < nSrcElem; ++srcElemi) + { + if (subBb.overlaps(calcSrcBox(srcElemi))) + { + procBoxes.append(subBb); + break; + } + } + } + } +} + + +void Foam::processorLODs::box::refineBox +( + const label boxi, + const labelList& srcAddr, + const treeBoundBox& origBox, + DynamicList<treeBoundBox>& procBoxes, + DynamicList<labelList>& procBoxElems, + DynamicList<label>& procNewToOld +) const +{ + // Create the new boxes + for (direction octant = 0; octant < 8; ++octant) + { + const treeBoundBox subBb(origBox.subBbox(octant)); + + // Identify the src elements for each box + DynamicList<label> newElems(srcAddr.size()/2); + + for (const label srcElemi : srcAddr) + { + if (subBb.overlaps(calcSrcBox(srcElemi))) + { + newElems.append(srcElemi); + } + } + + // Only keeping new box if it overlaps src objects + if (newElems.size()) + { + procBoxes.append(subBb); + procBoxElems.append(newElems); + procNewToOld.append(boxi); + } + } +} + + +bool Foam::processorLODs::box::doRefineBoxes +( + const label refineIter, + const label nSrcFaces, + const List<labelList>& refineFlags, + const labelList& nElems, + List<DynamicList<treeBoundBox>>& fixedBoxes +) +{ + PstreamBuffers pBufs(Pstream::commsTypes::nonBlocking); + + // Send refine info back for list of evolving src boxes + forAll(refineFlags, proci) + { + if (proci != Pstream::myProcNo()) + { + UOPstream toProc(proci, pBufs); + toProc << nElems[proci] << refineFlags[proci]; + } + } + + pBufs.finishedSends(); + + // Receive refine refinement actions from remote procs and use to refine + // local src boxes + bool refineBoxes = false; + label nElem = 0; + List<DynamicList<label>> newToOld(Pstream::nProcs()); + + + for (label proci = 0; proci < Pstream::nProcs(); ++proci) + { + if (proci == Pstream::myProcNo()) + { + continue; + } + + UIPstream fromProc(proci, pBufs); + nElem += readLabel(fromProc); + const labelList refineFlags(fromProc); + + const List<treeBoundBox>& procBoxes = boxes_[proci]; + DynamicList<treeBoundBox> newProcBoxes(procBoxes.size()); + DynamicList<labelList> newProcBoxElems(procBoxes.size()); + newToOld[proci].setCapacity(boxes_[proci].size()); + DynamicList<label>& newProcNewToOld = newToOld[proci]; + + + forAll(procBoxes, boxi) + { + if (refineFlags[boxi] == DROP) + { + // Skip box + } + else if (refineFlags[boxi] == REFINE) + { + if (refineIter > nStartUpIter) + { + // Can use locally cached info to speed up intersection + // tests + refineBox + ( + boxi, + boxSrcElems_[proci][boxi], + procBoxes[boxi], + newProcBoxes, + newProcBoxElems, + newProcNewToOld + ); + } + else + { + refineBox + ( + boxi, + refineIter, + nSrcFaces, + procBoxes[boxi], + newProcBoxes, + newProcBoxElems, + newProcNewToOld + ); + } + + refineBoxes = true; + } + else if (refineFlags[boxi] == FIXED) + { + fixedBoxes[proci].append(procBoxes[boxi]); + } + else + { + FatalErrorInFunction + << "Unhandled refine action " << refineFlags[boxi] + << abort(FatalError); + } + } + + // Only keeping boxes that are to be refined + boxes_[proci].transfer(newProcBoxes); + boxSrcElems_[proci].transfer(newProcBoxElems); + newToOld_[proci].transfer(newProcNewToOld); + } + + return returnReduce(refineBoxes, orOp<bool>()); +} + + +Foam::autoPtr<Foam::mapDistribute> Foam::processorLODs::box::createMap +( + const label nSrcElems, + const label nTgtElems +) +{ + // Store elements to send - will be used to build the mapDistribute + List<labelHashSet> fixedSendElems(Pstream::nProcs()); + + // List of local tgt elems to optimise searching fot tgt elements inside + // remote src boxes + List<List<labelList>> localTgtElems(Pstream::nProcs()); + + // Storage of boxes per processor - only useful for debugging + List<DynamicList<treeBoundBox>> fixedBoxes(Pstream::nProcs()); + + // Iterate to subdivide src boxes + label refinementIter = 1; + bool refineSrcBoxes = true; + while (refineSrcBoxes && (refinementIter <= nRefineIterMax_)) + { + // Per processor refinement info + List<labelList> refineFlags(Pstream::nProcs()); + labelList nElems(Pstream::nProcs(), 0); + + // Assess how many target elements intersect the source bounding boxes + // and use the info to flag how the source boxes should be refined + setRefineFlags + ( + refinementIter, + nTgtElems, + fixedSendElems, + localTgtElems, + refineFlags, + nElems + ); + + // Refine the source bounding boxes + refineSrcBoxes = + doRefineBoxes + ( + refinementIter, + nSrcElems, + refineFlags, + nElems, + fixedBoxes + ); + + ++refinementIter; + + if (debug > 1) + { + // Include any boxes that are still evolving + List<DynamicList<treeBoundBox>> allBoxes(fixedBoxes); + forAll(allBoxes, proci) + { + allBoxes[proci].append(boxes_[proci]); + } + writeBoxes(allBoxes, refinementIter); + } + } + + if (debug) + { + Pout<< "Local src boxes after " << refinementIter-1 << " iterations:" + << nl; + + forAll(fixedBoxes, proci) + { + // Include any boxes that are still evolving in box count + label nBox = fixedBoxes[proci].size() + boxes_[proci].size(); + Pout<< " proc:" << proci << " nBoxes:" << nBox << nl; + } + Pout<< endl; + } + + // Convert send elems into a List<labelList> + List<labelList> sendElems(Pstream::nProcs()); + forAll(localTgtElems, proci) + { + if (proci == Pstream::myProcNo() && nSrcElems) + { + sendElems[proci] = identity(nTgtElems); + } + else + { + labelHashSet& allIDs = fixedSendElems[proci]; + + const List<labelList>& procBoxElems = localTgtElems[proci]; + + for (const labelList& elems: procBoxElems) + { + allIDs.insert(elems); + } + + sendElems[proci] = allIDs.toc(); + } + } + + fixedSendElems.clear(); + localTgtElems.clear(); + + if (debug) + { + Pout<< "Local objects: " << nTgtElems << " Send map:" << nl + << tab << "proc" << tab << "objects" << endl; + + forAll(sendElems, proci) + { + Pout<< tab << proci << tab << sendElems[proci].size() + << endl; + } + } + + return createLODMap(sendElems); +} + + +Foam::autoPtr<Foam::mapDistribute> Foam::processorLODs::box::createLODMap +( + List<labelList>& sendElems +) const +{ + // Send over how many objects I need to receive + const label localProci = Pstream::myProcNo(); + labelListList sendSizes(Pstream::nProcs()); + sendSizes[localProci].setSize(Pstream::nProcs()); + forAll(sendElems, proci) + { + sendSizes[localProci][proci] = sendElems[proci].size(); + } + Pstream::gatherList(sendSizes); + Pstream::scatterList(sendSizes); + + + // Determine order of receiving + labelListList constructMap(Pstream::nProcs()); + + // My local segment first + constructMap[localProci] = identity(sendElems[localProci].size()); + + label segmenti = constructMap[localProci].size(); + forAll(constructMap, proci) + { + if (proci != localProci) + { + // What I need to receive is what other processor is sending to me + label nRecv = sendSizes[proci][localProci]; + constructMap[proci].setSize(nRecv); + + for (label& addr : constructMap[proci]) + { + addr = segmenti++; + } + } + } + + autoPtr<mapDistribute> mapPtr + ( + new mapDistribute + ( + segmenti, // size after construction + std::move(sendElems), + std::move(constructMap) + ) + ); + + return mapPtr; +} + + +// * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * * // + +Foam::processorLODs::box::box +( + const UList<point>& srcPoints, + const UList<point>& tgtPoints, + const label maxObjectsPerLeaf, + const label nObjectsOfType, + const label nRefineIterMax +) +: + processorLOD(maxObjectsPerLeaf, nObjectsOfType), + srcPoints_(srcPoints), + tgtPoints_(tgtPoints), + boxes_(Pstream::nProcs()), + nRefineIterMax_(nRefineIterMax), + newToOld_(Pstream::nProcs()), + boxSrcElems_(Pstream::nProcs()) +{ + // Initialise each processor with a single box large enough to include all + // of its local src points + if (srcPoints_.size()) + { + forAll(boxes_, proci) + { + List<treeBoundBox>& procBoxes = boxes_[proci]; + + // Note: inflate to ease overlap operations and to handle 2-D + // axis-aligned objects + treeBoundBox srcBb(srcPoints_); + srcBb.inflate(0.01); + + DynamicList<treeBoundBox> newProcBoxes(1); + newProcBoxes.append(srcBb); + procBoxes.transfer(newProcBoxes); + } + } +} + + +// ************************************************************************* // diff --git a/src/meshTools/processorLOD/box/box.H b/src/meshTools/processorLOD/box/box.H new file mode 100644 index 0000000000000000000000000000000000000000..89214a22ee00001cc4eca05d317fbe340ed10c93 --- /dev/null +++ b/src/meshTools/processorLOD/box/box.H @@ -0,0 +1,206 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2017 OpeCFD Ltd. + \\/ 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 <http://www.gnu.org/licenses/>. + +Class + Foam::processorLODs::box + +Description + Creates the parallel distribution map by describing the source and target + objects using box shapes. + + A single box is created for the source object, which is then split using + 2x2x2 refinement based on the number of remote target objects that overlap. + The refinement is local between communicating processor pairs, where the + refinement continues until a threshold number of remote target objects per + source box is achieved. + +\*---------------------------------------------------------------------------*/ + +#ifndef processorLODs_box +#define processorLODs_box + +#include "processorLOD.H" +#include "treeBoundBox.H" +#include "HashSet.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +namespace processorLODs +{ + +/*---------------------------------------------------------------------------*\ + Class Box Declaration +\*---------------------------------------------------------------------------*/ + +class box +: + public processorLOD +{ +protected: + + // Protected data + + // Flags to indicate what to do with a box + + //- Drop/discard + static const label DROP; + + //- Refine + static const label REFINE; + + //- Fixed - do not touch + static const label FIXED; + + + //- Reference to the source points + const UList<point>& srcPoints_; + + //- Reference to the target points + const UList<point>& tgtPoints_; + + //- Per processor, the list of src bound boxes + // Note: using treeBoundBox to take advantage of subBbox() method + List<List<treeBoundBox>> boxes_; + + //- Maximum number of refinement iterations + label nRefineIterMax_; + + + // Caching controls + + //- Number of iterations before element indices are cached + static const label nStartUpIter; + + //- Addressing per proc of new to old bound boxes + List<labelList> newToOld_; + + //- Indices of elements in the src boxes + List<List<labelList>> boxSrcElems_; + + + // Private Member Functions + + //- Helper function to write the boxes in OBJ format + void writeBoxes + ( + const List<DynamicList<treeBoundBox>>& fixedBoxes, + const label iter + ) const; + + + virtual boundBox calcSrcBox(const label srcObji) const = 0; + virtual boundBox calcTgtBox(const label tgtObji) const = 0; + + //- Set the box refinement flags + void setRefineFlags + ( + const label refineIter, + const label nTgtObjects, + List<labelHashSet>& fixedSendElems, + List<List<labelList>>& localTgtElems, + List<labelList>& refineFlags, + labelList& nElems + ) const; + + void refineBox + ( + const label boxi, + const label refineIter, + const label nSrcElem, + const treeBoundBox& origBox, + DynamicList<treeBoundBox>& procBoxes, + DynamicList<labelList>& procBoxElems, + DynamicList<label>& procNewToOld + ) const; + + void refineBox + ( + const label boxi, + const labelList& srcAddr, + const treeBoundBox& origBox, + DynamicList<treeBoundBox>& procBoxes, + DynamicList<labelList>& procBoxElems, + DynamicList<label>& procNewToOld + ) const; + + + //- Apply the box refinements + // \return true if still refining + bool doRefineBoxes + ( + const label refineIter, + const label nSrcFaces, + const List<labelList>& refineFlags, + const labelList& nElems, + List<DynamicList<treeBoundBox>>& fixedBoxes + ); + + autoPtr<mapDistribute> createMap + ( + const label nSrcElems, + const label nTgtElems + ); + + //- Use the current list of send elements to create the mapDistribute + autoPtr<mapDistribute> createLODMap + ( + List<labelList>& sendElems + ) const; + + +public: + + //- Runtime type information + TypeName("box"); + + //- Construct from list of points + box + ( + const UList<point>& srcPoints, + const UList<point>& tgtPoints, + const label maxObjectsPerLeaf, + const label nObjectsOfType, + const label nRefineIterMax = 100 + ); + + //- Destructor + virtual ~box() = default; +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace processorLODs + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/meshTools/processorLOD/cellBox/cellBox.C b/src/meshTools/processorLOD/cellBox/cellBox.C new file mode 100644 index 0000000000000000000000000000000000000000..db505dd661cc32d157ad8c8fe3ac1d05914ed089 --- /dev/null +++ b/src/meshTools/processorLOD/cellBox/cellBox.C @@ -0,0 +1,110 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2017 OpenCFD Ltd. + \\/ 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 <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "cellBox.H" +#include "mapDistribute.H" + +namespace Foam +{ +namespace processorLODs +{ + defineTypeNameAndDebug(cellBox, 0); +} +} + + +// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * // + +Foam::boundBox Foam::processorLODs::cellBox::calcSrcBox +( + const label srcObji +) const +{ + const UList<label>& cellFaces = srcCells_[srcObji]; + + boundBox bb(srcPoints_, srcFaces_[cellFaces[0]], false); + for (label i = 1; i < cellFaces.size(); ++i) + { + bb.add(srcPoints_, srcFaces_[cellFaces[i]]); + } + + return bb; +} + + +Foam::boundBox Foam::processorLODs::cellBox::calcTgtBox +( + const label tgtObji +) const +{ + const UList<label>& cellFaces = tgtCells_[tgtObji]; + + boundBox bb(tgtPoints_, tgtFaces_[cellFaces[0]], false); + for (label i = 1; i < cellFaces.size(); ++i) + { + bb.add(tgtPoints_, tgtFaces_[cellFaces[i]]); + } + + return bb; +} + + +// * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * * // + +Foam::processorLODs::cellBox::cellBox +( + const cellList& srcCells, + const faceList& srcFaces, + const UList<point>& srcPoints, + const cellList& tgtCells, + const faceList& tgtFaces, + const UList<point>& tgtPoints, + const label maxObjectsPerLeaf, + const label nObjectsOfType, + const label nRefineIterMax +) +: + faceBox + ( + srcFaces, + srcPoints, + tgtFaces, + tgtPoints, + maxObjectsPerLeaf, + nObjectsOfType, + nRefineIterMax + ), + srcCells_(srcCells), + tgtCells_(tgtCells) +{} + + +Foam::autoPtr<Foam::mapDistribute> Foam::processorLODs::cellBox::map() +{ + return createMap(srcCells_.size(), tgtCells_.size()); +} + + +// ************************************************************************* // diff --git a/src/meshTools/processorLOD/cellBox/cellBox.H b/src/meshTools/processorLOD/cellBox/cellBox.H new file mode 100644 index 0000000000000000000000000000000000000000..69bcf3032e3639454df1ae3a42e67ee93b5c571f --- /dev/null +++ b/src/meshTools/processorLOD/cellBox/cellBox.H @@ -0,0 +1,120 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2017 OpeCFD Ltd. + \\/ 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 <http://www.gnu.org/licenses/>. + +Class + Foam::processorLODs::cellBox + +Description + Creates the parallel distribution map by describing the source and target + objects using box shapes. + + A single box is created for the source object, which is then split using + 2x2x2 refinement based on the number of remote target objects that overlap. + The refinement is local between communicating processor pairs, where the + refinement continues until a threshold number of remote target objects per + source box is achieved. + +\*---------------------------------------------------------------------------*/ + +#ifndef processorLODs_cellBox +#define processorLODs_cellBox + +#include "faceBox.H" +#include "cellList.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +namespace processorLODs +{ + +/*---------------------------------------------------------------------------*\ + Class cellBox Declaration +\*---------------------------------------------------------------------------*/ + +class cellBox +: + public faceBox +{ +private: + + // Private data + + //- Reference to the source face list + const cellList& srcCells_; + + //- Reference to the target face list + const cellList& tgtCells_; + + + // Private Member Functions + + virtual boundBox calcSrcBox(const label srcObji) const; + virtual boundBox calcTgtBox(const label tgtObji) const; + + +public: + + //- Runtime type information + TypeName("box"); + + //- Construct from list of points + cellBox + ( + const cellList& srcCells, + const faceList& srcFaces, + const UList<point>& srcPoints, + const cellList& tgtCells, + const faceList& tgtFaces, + const UList<point>& tgtPoints, + const label maxObjectsPerLeaf, + const label nObjectsOfType, + const label nRefineIterMax = 100 + ); + + //- Destructor + virtual ~cellBox() = default; + + + // Member Functions + + //- Return the parallel distribution map + virtual autoPtr<mapDistribute> map(); +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace processorLODs + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/meshTools/processorLOD/faceBox/faceBox.C b/src/meshTools/processorLOD/faceBox/faceBox.C new file mode 100644 index 0000000000000000000000000000000000000000..43e72a365ee7dd9ab683254c9b452603ed40ee6e --- /dev/null +++ b/src/meshTools/processorLOD/faceBox/faceBox.C @@ -0,0 +1,82 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2017 OpenCFD Ltd. + \\/ 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 <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "faceBox.H" +#include "mapDistribute.H" + +namespace Foam +{ +namespace processorLODs +{ + defineTypeNameAndDebug(faceBox, 0); +} +} + +// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * // + +Foam::boundBox Foam::processorLODs::faceBox::calcSrcBox +( + const label srcObji +) const +{ + return boundBox(srcPoints_, srcFaces_[srcObji], false); +} + + +Foam::boundBox Foam::processorLODs::faceBox::calcTgtBox +( + const label tgtObji +) const +{ + return boundBox(tgtPoints_, tgtFaces_[tgtObji], false); +} + + +// * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * * // + +Foam::processorLODs::faceBox::faceBox +( + const faceList& srcFaces, + const UList<point>& srcPoints, + const faceList& tgtFaces, + const UList<point>& tgtPoints, + const label maxObjectsPerLeaf, + const label nObjectsOfType, + const label nRefineIterMax +) +: + box(srcPoints, tgtPoints, maxObjectsPerLeaf, nObjectsOfType), + srcFaces_(srcFaces), + tgtFaces_(tgtFaces) +{} + + +Foam::autoPtr<Foam::mapDistribute> Foam::processorLODs::faceBox::map() +{ + return createMap(srcFaces_.size(), tgtFaces_.size()); +} + + +// ************************************************************************* // diff --git a/src/meshTools/processorLOD/faceBox/faceBox.H b/src/meshTools/processorLOD/faceBox/faceBox.H new file mode 100644 index 0000000000000000000000000000000000000000..c504dde4af48ad074a591c1d2e36f94345a8889c --- /dev/null +++ b/src/meshTools/processorLOD/faceBox/faceBox.H @@ -0,0 +1,117 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2017 OpeCFD Ltd. + \\/ 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 <http://www.gnu.org/licenses/>. + +Class + Foam::processorLODs::faceBox + +Description + Creates the parallel distribution map by describing the source and target + objects using box shapes. + + A single box is created for the source object, which is then split using + 2x2x2 refinement based on the number of remote target objects that overlap. + The refinement is local between communicating processor pairs, where the + refinement continues until a threshold number of remote target objects per + source box is achieved. + +\*---------------------------------------------------------------------------*/ + +#ifndef processorLODs_faceBox +#define processorLODs_faceBox + +#include "box.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +namespace processorLODs +{ + +/*---------------------------------------------------------------------------*\ + Class faceBox Declaration +\*---------------------------------------------------------------------------*/ + +class faceBox +: + public box +{ +protected: + + // Protected data + + //- Reference to the source face list + const faceList& srcFaces_; + + //- Reference to the target face list + const faceList& tgtFaces_; + + + // Protected Member Functions + + virtual boundBox calcSrcBox(const label srcObji) const; + virtual boundBox calcTgtBox(const label tgtObji) const; + + +public: + + //- Runtime type information + TypeName("box"); + + //- Construct from list of points + faceBox + ( + const faceList& srcFaces, + const UList<point>& srcPoints, + const faceList& tgtFaces, + const UList<point>& tgtPoints, + const label maxObjectsPerLeaf, + const label nObjectsOfType, + const label nRefineIterMax = 100 + ); + + //- Destructor + virtual ~faceBox() = default; + + + // Member Functions + + //- Return the parallel distribution map + virtual autoPtr<mapDistribute> map(); +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace processorLODs + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/meshTools/processorLOD/processorLOD/processorLOD.C b/src/meshTools/processorLOD/processorLOD/processorLOD.C new file mode 100644 index 0000000000000000000000000000000000000000..2039c87692284d39c186fd732fddf0dc3c0334b3 --- /dev/null +++ b/src/meshTools/processorLOD/processorLOD/processorLOD.C @@ -0,0 +1,46 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2017 OpenCFD Ltd. + \\/ 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 <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "processorLOD.H" + +namespace Foam +{ + defineTypeNameAndDebug(processorLOD, 0); +} + +// * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * * // + +Foam::processorLOD::processorLOD +( + const label maxObjectsPerLeaf, + const label nObjectsOfType +) +: + maxObjectsPerLeaf_(maxObjectsPerLeaf), + nObjectsOfType_(nObjectsOfType) +{} + + +// ************************************************************************* // diff --git a/src/meshTools/processorLOD/processorLOD/processorLOD.H b/src/meshTools/processorLOD/processorLOD/processorLOD.H new file mode 100644 index 0000000000000000000000000000000000000000..94c20c63b070e320863a0abd5ddf8f5e1d85c113 --- /dev/null +++ b/src/meshTools/processorLOD/processorLOD/processorLOD.H @@ -0,0 +1,97 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2017 OpenCFD Ltd. + \\/ 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 <http://www.gnu.org/licenses/>. + +Class + Foam::processorLOD + +Description + Base class to generate a parallel distribution map for sending sufficient + target objects to cover a description of the source object, based on + processor Level Of Detail (LOD) shapes + +\*---------------------------------------------------------------------------*/ + +#ifndef processorLOD_H +#define processorLOD_H + +#include "autoPtr.H" +#include "typeInfo.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +class mapDistribute; + +/*---------------------------------------------------------------------------*\ + Class processorLOD Declaration +\*---------------------------------------------------------------------------*/ + +class processorLOD +{ + +protected: + + // Protected data + + //- Maximum number of objects per leaf + label maxObjectsPerLeaf_; + + //- Number of objects of this type, e.g. number of faces/cells on this + //- processor + label nObjectsOfType_; + + +public: + + //- Runtime type information + TypeName("processorLOD"); + + //- Construct from components + processorLOD + ( + const label maxObjectsPerLeaf, + const label nObjectsOfType + ); + + //- Destructor + virtual ~processorLOD() = default; + + + // Member Functions + + //- Return the parallel distribution map + virtual autoPtr<mapDistribute> map() = 0; +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/overset/cellCellStencil/cellVolumeWeight/cellVolumeWeightCellCellStencil.C b/src/overset/cellCellStencil/cellVolumeWeight/cellVolumeWeightCellCellStencil.C index 8ffc7f6c6e8fcb3e15cd77930023b98a31d13ace..1c9a5e72c4022f530b4044627603a994b810ae69 100644 --- a/src/overset/cellCellStencil/cellVolumeWeight/cellVolumeWeightCellCellStencil.C +++ b/src/overset/cellCellStencil/cellVolumeWeight/cellVolumeWeightCellCellStencil.C @@ -784,9 +784,10 @@ bool Foam::cellCellStencils::cellVolumeWeight::update() ( srcMesh, tgtMesh, - meshToMesh::imCellVolumeWeight, + meshToMesh::interpolationMethod::imCellVolumeWeight, HashTable<word>(0), // patchMap, wordList(0), // cuttingPatches + meshToMesh::procMapMethod::pmAABB, false // do not normalise ); diff --git a/src/sampling/meshToMesh/calcMethod/meshToMeshMethod/meshToMeshMethod.C b/src/sampling/meshToMesh/calcMethod/meshToMeshMethod/meshToMeshMethod.C index afb6b727dc9d2cc526b468ae17c6be84c1aa5e5d..ef21a395f115da91e79bc8a21e52145cead9242e 100644 --- a/src/sampling/meshToMesh/calcMethod/meshToMeshMethod/meshToMeshMethod.C +++ b/src/sampling/meshToMesh/calcMethod/meshToMeshMethod/meshToMeshMethod.C @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2013-2014 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2018 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -84,7 +84,14 @@ bool Foam::meshToMeshMethod::intersect tetOverlapVolume overlapEngine; - treeBoundBox bbTgtCell(tgt_.points(), tgt_.cellPoints()[tgtCelli]); + // Note: avoid demand-driven construction of cellPoints + // treeBoundBox bbTgtCell(tgt_.points(), tgt_.cellPoints()[tgtCelli]); + const UList<label>& cellFaces = tgt_.cells()[tgtCelli]; + treeBoundBox bbTgtCell(tgt_.points(), tgt_.faces()[cellFaces[0]]); + for (label i = 1; i < cellFaces.size(); ++i) + { + bbTgtCell.add(tgt_.points(), tgt_.faces()[cellFaces[i]]); + } return overlapEngine.cellCellOverlapMinDecomp ( @@ -106,7 +113,14 @@ Foam::scalar Foam::meshToMeshMethod::interVol { tetOverlapVolume overlapEngine; - treeBoundBox bbTgtCell(tgt_.points(), tgt_.cellPoints()[tgtCelli]); + // Note: avoid demand-driven construction of cellPoints + // treeBoundBox bbTgtCell(tgt_.points(), tgt_.cellPoints()[tgtCelli]); + const UList<label>& cellFaces = tgt_.cells()[tgtCelli]; + treeBoundBox bbTgtCell(tgt_.points(), tgt_.faces()[cellFaces[0]]); + for (label i = 1; i < cellFaces.size(); ++i) + { + bbTgtCell.add(tgt_.points(), tgt_.faces()[cellFaces[i]]); + } scalar vol = overlapEngine.cellCellOverlapVolumeMinDecomp ( @@ -124,21 +138,28 @@ Foam::scalar Foam::meshToMeshMethod::interVol Foam::Tuple2<Foam::scalar, Foam::point> Foam::meshToMeshMethod::interVolAndCentroid ( - const label srcCellI, - const label tgtCellI + const label srcCelli, + const label tgtCelli ) { tetOverlapVolume overlapEngine; - treeBoundBox bbTgtCell(tgt_.points(), tgt_.cellPoints()[tgtCellI]); + // Note: avoid demand-driven construction of cellPoints + // treeBoundBox bbTgtCell(tgt_.points(), tgt_.cellPoints()[tgtCelli]); + const UList<label>& cellFaces = tgt_.cells()[tgtCelli]; + treeBoundBox bbTgtCell(tgt_.points(), tgt_.faces()[cellFaces[0]]); + for (label i = 1; i < cellFaces.size(); ++i) + { + bbTgtCell.add(tgt_.points(), tgt_.faces()[cellFaces[i]]); + } Tuple2<scalar, point> volAndInertia = overlapEngine.cellCellOverlapMomentMinDecomp ( src_, - srcCellI, + srcCelli, tgt_, - tgtCellI, + tgtCelli, bbTgtCell ); diff --git a/src/sampling/meshToMesh/meshToMesh.C b/src/sampling/meshToMesh/meshToMesh.C index d4ab2b7449d5b16f31633643758e8582f1bdc10e..2c6a5e8ab65fbefc82bf39f99078194ee66bbfe3 100644 --- a/src/sampling/meshToMesh/meshToMesh.C +++ b/src/sampling/meshToMesh/meshToMesh.C @@ -52,6 +52,17 @@ Foam::meshToMesh::interpolationMethodNames_ }; +const Foam::Enum +< + Foam::meshToMesh::procMapMethod +> +Foam::meshToMesh::procMapMethodNames_ +{ + { procMapMethod::pmAABB, "AABB" }, + { procMapMethod::pmLOD, "LOD" }, +}; + + // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // template<> @@ -628,18 +639,18 @@ Foam::meshToMesh::interpolationMethodAMI(const interpolationMethod method) { switch (method) { - case imDirect: + case interpolationMethod::imDirect: { return AMIPatchToPatchInterpolation::imDirect; break; } - case imMapNearest: + case interpolationMethod::imMapNearest: { return AMIPatchToPatchInterpolation::imMapNearest; break; } - case imCellVolumeWeight: - case imCorrectedCellVolumeWeight: + case interpolationMethod::imCellVolumeWeight: + case interpolationMethod::imCorrectedCellVolumeWeight: { return AMIPatchToPatchInterpolation::imFaceAreaWeight; break; @@ -647,7 +658,7 @@ Foam::meshToMesh::interpolationMethodAMI(const interpolationMethod method) default: { FatalErrorInFunction - << "Unhandled enumeration " << method + << "Unhandled enumeration " << interpolationMethodNames_[method] << abort(FatalError); } } @@ -827,11 +838,13 @@ Foam::meshToMesh::meshToMesh const polyMesh& src, const polyMesh& tgt, const interpolationMethod& method, + const procMapMethod& mapMethod, bool interpAllPatches ) : srcRegion_(src), tgtRegion_(tgt), + procMapMethod_(mapMethod), srcPatchID_(), tgtPatchID_(), patchAMIs_(), @@ -865,11 +878,13 @@ Foam::meshToMesh::meshToMesh const polyMesh& tgt, const word& methodName, const word& AMIMethodName, + const procMapMethod& mapMethod, bool interpAllPatches ) : srcRegion_(src), tgtRegion_(tgt), + procMapMethod_(mapMethod), srcPatchID_(), tgtPatchID_(), patchAMIs_(), @@ -896,11 +911,13 @@ Foam::meshToMesh::meshToMesh const interpolationMethod& method, const HashTable<word>& patchMap, const wordList& cuttingPatches, + const procMapMethod& mapMethod, const bool normalise ) : srcRegion_(src), tgtRegion_(tgt), + procMapMethod_(mapMethod), srcPatchID_(), tgtPatchID_(), patchAMIs_(), @@ -936,11 +953,13 @@ Foam::meshToMesh::meshToMesh const word& AMIMethodName, // boundary mapping const HashTable<word>& patchMap, const wordList& cuttingPatches, + const procMapMethod& mapMethod, const bool normalise ) : srcRegion_(src), tgtRegion_(tgt), + procMapMethod_(mapMethod), srcPatchID_(), tgtPatchID_(), patchAMIs_(), diff --git a/src/sampling/meshToMesh/meshToMesh.H b/src/sampling/meshToMesh/meshToMesh.H index e1567c18a4bf029691473d285c497a4c891b8b7b..40aaaf329a09ffbeda4288b1cb989c4b647a1091 100644 --- a/src/sampling/meshToMesh/meshToMesh.H +++ b/src/sampling/meshToMesh/meshToMesh.H @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2012-2016 OpenFOAM Foundation - \\/ M anipulation | Copyright (C) 2015-2016 OpenCFD Ltd. + \\/ M anipulation | Copyright (C) 2015-2018 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -66,7 +66,7 @@ public: // Public data types //- Enumeration specifying interpolation method - enum interpolationMethod + enum class interpolationMethod { imDirect, imMapNearest, @@ -76,6 +76,15 @@ public: static const Enum<interpolationMethod> interpolationMethodNames_; + //- Enumeration specifying processor parallel map construction method + enum class procMapMethod + { + pmAABB, + pmLOD + }; + + static const Enum<procMapMethod> procMapMethodNames_; + private: // Private data @@ -86,6 +95,9 @@ private: //- Reference to the target mesh const polyMesh& tgtRegion_; + //- Processor parallel map construction method + procMapMethod procMapMethod_; + //- List of target patch IDs per source patch (local index) List<label> srcPatchID_; @@ -301,6 +313,7 @@ public: const polyMesh& src, const polyMesh& tgt, const interpolationMethod& method, + const procMapMethod& mapMethod = procMapMethod::pmAABB, const bool interpAllPatches = true ); @@ -311,6 +324,7 @@ public: const polyMesh& tgt, const word& methodName, // internal mapping const word& AMIMethodName, // boundary mapping + const procMapMethod& mapMethod = procMapMethod::pmAABB, const bool interpAllPatches = true ); @@ -322,6 +336,7 @@ public: const interpolationMethod& method, const HashTable<word>& patchMap, const wordList& cuttingPatches, + const procMapMethod& mapMethod = procMapMethod::pmAABB, const bool normalise = true ); @@ -335,6 +350,7 @@ public: const word& AMIMethodName, // boundary mapping const HashTable<word>& patchMap, const wordList& cuttingPatches, + const procMapMethod& mapMethod = procMapMethod::pmAABB, const bool normalise = true ); diff --git a/src/sampling/meshToMesh/meshToMeshParallelOps.C b/src/sampling/meshToMesh/meshToMeshParallelOps.C index bae3aa442a220a2b72e1fc55934826aa571c93de..b391a6132f1222198cfb46c8675a1b653727ca5b 100644 --- a/src/sampling/meshToMesh/meshToMeshParallelOps.C +++ b/src/sampling/meshToMesh/meshToMeshParallelOps.C @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2012-2017 OpenFOAM Foundation - \\/ M anipulation | Copyright (C) 2015-2017 OpenCFD Ltd. + \\/ M anipulation | Copyright (C) 2015-2018 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -31,6 +31,7 @@ License #include "processorPolyPatch.H" #include "SubField.H" #include "AABBTree.H" +#include "cellBox.H" // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // @@ -98,12 +99,12 @@ Foam::label Foam::meshToMesh::calcOverlappingProcs { const treeBoundBoxList& bbp = procBb[proci]; - forAll(bbp, bbi) + for (const treeBoundBox& b : bbp) { - if (bbp[bbi].overlaps(bb)) + if (b.overlaps(bb)) { overlaps[proci] = true; - nOverlaps++; + ++nOverlaps; break; } } @@ -119,139 +120,179 @@ Foam::autoPtr<Foam::mapDistribute> Foam::meshToMesh::calcProcMap const polyMesh& tgt ) const { - // get decomposition of cells on src mesh - List<treeBoundBoxList> procBb(Pstream::nProcs()); - - if (src.nCells() > 0) + switch (procMapMethod_) { - procBb[Pstream::myProcNo()] = AABBTree<labelList> - ( - src.cellPoints(), - src.points(), - false - ).boundBoxes(); - } - else - { - procBb[Pstream::myProcNo()] = treeBoundBoxList(); - } - + case procMapMethod::pmLOD: + { + Info<< "meshToMesh: Using processorLOD method" << endl; + + // Create processor map of overlapping faces. This map gets + // (possibly remote) cells from the tgt mesh such that they + // (together) cover all of the src mesh + label nGlobalSrcCells = + returnReduce(src.cells().size(), sumOp<label>()); + label cellsPerBox = max(1, 0.001*nGlobalSrcCells); + typename processorLODs::cellBox boxLOD + ( + src.cells(), + src.faces(), + src.points(), + tgt.cells(), + tgt.faces(), + tgt.points(), + cellsPerBox, + src.nCells() + ); + + return boxLOD.map(); + break; + } + default: + { + Info<< "meshToMesh: Using AABBTree method" << endl; - Pstream::gatherList(procBb); - Pstream::scatterList(procBb); + // get decomposition of cells on src mesh + List<treeBoundBoxList> procBb(Pstream::nProcs()); + if (src.nCells() > 0) + { + procBb[Pstream::myProcNo()] = AABBTree<labelList> + ( + src.cellPoints(), + src.points(), + false + ).boundBoxes(); + } + else + { + procBb[Pstream::myProcNo()] = treeBoundBoxList(); + } - if (debug) - { - InfoInFunction - << "Determining extent of src mesh per processor:" << nl - << "\tproc\tbb" << endl; - forAll(procBb, proci) - { - Info<< '\t' << proci << '\t' << procBb[proci] << endl; - } - } + Pstream::gatherList(procBb); + Pstream::scatterList(procBb); - // determine which cells of tgt mesh overlaps src mesh per proc - const cellList& cells = tgt.cells(); - const faceList& faces = tgt.faces(); - const pointField& points = tgt.points(); - labelListList sendMap; + if (debug) + { + InfoInFunction + << "Determining extent of src mesh per processor:" << nl + << "\tproc\tbb" << endl; + forAll(procBb, proci) + { + Info<< '\t' << proci << '\t' << procBb[proci] << endl; + } + } - { - // per processor indices into all segments to send - List<DynamicList<label>> dynSendMap(Pstream::nProcs()); - label iniSize = floor(tgt.nCells()/Pstream::nProcs()); - forAll(dynSendMap, proci) - { - dynSendMap[proci].setCapacity(iniSize); - } + // determine which cells of tgt mesh overlaps src mesh per proc + const cellList& cells = tgt.cells(); + const faceList& faces = tgt.faces(); + const pointField& points = tgt.points(); - // work array - whether src processor bb overlaps the tgt cell bounds - boolList procBbOverlaps(Pstream::nProcs()); - forAll(cells, celli) - { - const cell& c = cells[celli]; + labelListList sendMap; - // determine bounding box of tgt cell - boundBox cellBb(boundBox::invertedBox); - forAll(c, facei) { - const face& f = faces[c[facei]]; - forAll(f, fp) + // per processor indices into all segments to send + List<DynamicList<label>> dynSendMap(Pstream::nProcs()); + label iniSize = floor(tgt.nCells()/Pstream::nProcs()); + + forAll(dynSendMap, proci) { - cellBb.add(points, f); + dynSendMap[proci].setCapacity(iniSize); + } + + // work array - whether src processor bb overlaps the tgt cell + // bounds + boolList procBbOverlaps(Pstream::nProcs()); + forAll(cells, celli) + { + const cell& c = cells[celli]; + + // determine bounding box of tgt cell + boundBox cellBb(boundBox::invertedBox); + forAll(c, facei) + { + const face& f = faces[c[facei]]; + forAll(f, fp) + { + cellBb.add(points, f); + } + } + + // find the overlapping tgt cells on each src processor + (void)calcOverlappingProcs(procBb, cellBb, procBbOverlaps); + + forAll(procBbOverlaps, proci) + { + if (procBbOverlaps[proci]) + { + dynSendMap[proci].append(celli); + } + } } - } - // find the overlapping tgt cells on each src processor - (void)calcOverlappingProcs(procBb, cellBb, procBbOverlaps); + // convert dynamicList to labelList + sendMap.setSize(Pstream::nProcs()); + forAll(sendMap, proci) + { + sendMap[proci].transfer(dynSendMap[proci]); + } + } - forAll(procBbOverlaps, proci) + // debug printing + if (debug) { - if (procBbOverlaps[proci]) + Pout<< "Of my " << cells.size() + << " target cells I need to send to:" << nl + << "\tproc\tcells" << endl; + forAll(sendMap, proci) { - dynSendMap[proci].append(celli); + Pout<< '\t' << proci << '\t' << sendMap[proci].size() + << endl; } } - } - // convert dynamicList to labelList - sendMap.setSize(Pstream::nProcs()); - forAll(sendMap, proci) - { - sendMap[proci].transfer(dynSendMap[proci]); - } - } - // debug printing - if (debug) - { - Pout<< "Of my " << cells.size() << " target cells I need to send to:" - << nl << "\tproc\tcells" << endl; - forAll(sendMap, proci) - { - Pout<< '\t' << proci << '\t' << sendMap[proci].size() << endl; - } - } + // send over how many tgt cells I need to receive from each + // processor + labelListList sendSizes(Pstream::nProcs()); + sendSizes[Pstream::myProcNo()].setSize(Pstream::nProcs()); + forAll(sendMap, proci) + { + sendSizes[Pstream::myProcNo()][proci] = sendMap[proci].size(); + } + Pstream::gatherList(sendSizes); + Pstream::scatterList(sendSizes); - // send over how many tgt cells I need to receive from each processor - labelListList sendSizes(Pstream::nProcs()); - sendSizes[Pstream::myProcNo()].setSize(Pstream::nProcs()); - forAll(sendMap, proci) - { - sendSizes[Pstream::myProcNo()][proci] = sendMap[proci].size(); - } - Pstream::gatherList(sendSizes); - Pstream::scatterList(sendSizes); + // determine order of receiving + labelListList constructMap(Pstream::nProcs()); + label segmentI = 0; + forAll(constructMap, proci) + { + // what I need to receive is what other processor is sending + // to me + label nRecv = sendSizes[proci][Pstream::myProcNo()]; + constructMap[proci].setSize(nRecv); - // determine order of receiving - labelListList constructMap(Pstream::nProcs()); + for (label i = 0; i < nRecv; i++) + { + constructMap[proci][i] = segmentI++; + } + } - label segmentI = 0; - forAll(constructMap, proci) - { - // what I need to receive is what other processor is sending to me - label nRecv = sendSizes[proci][Pstream::myProcNo()]; - constructMap[proci].setSize(nRecv); + return autoPtr<mapDistribute>::New + ( + segmentI, // size after construction + std::move(sendMap), + std::move(constructMap) + ); - for (label i = 0; i < nRecv; i++) - { - constructMap[proci][i] = segmentI++; + break; } } - - return autoPtr<mapDistribute>::New - ( - segmentI, // size after construction - std::move(sendMap), - std::move(constructMap) - ); }