From d1b53557e2e5d155d434f49d915c1c78dc1afebc Mon Sep 17 00:00:00 2001 From: Will Bainbridge Date: Thu, 1 Sep 2022 08:31:16 +0100 Subject: [PATCH 1/5] mappedPatchBase: Added patchToPatch as a sampling mode This mode uses the patchToPatch system (the same one used by NCC) for coupling two patches. It can be selected for a patch (e.g., in a blockMeshDict) in the following way: fluid_to_solid { type mappedWall; sampleMode patchToPatch; sampleRegion solid; samplePatch solid_to_fluid; patchToPatchMode intersection; faces ( (0 1 2 3) ... ); } The "patchToPatchMode" can be one of the following: "intersection": Values obtained by weighting contributions from sampled faces with the intersected area between the faces. Equivalent to the nearestPatchFaceAMI sampleMode (which will be removed in a future commit). "inverseDistance": Values obtained by inverse-distance weighting between a small stencil of nearby sampled faces. "nearest": Take the value from the nearest sampled face. "matching": As nearest, but with checks to ensure that the mapping is one-to-one. To be used for mapping between identical patches. The intention is that patchToPatch will become the only sampleMode, and the four options above will become the options which determine how mapping is performed. Cell-to-patch mapping will be transferred into a separate class as its use cases essentially never intersect with those of patch-to-patch mapping. --- .../field/nearWallFields/nearWallFields.C | 1 - src/meshTools/Make/files | 1 + .../mappedPolyPatch/mappedPatchBase.C | 70 +++++- .../mappedPolyPatch/mappedPatchBase.H | 22 +- .../mappedPolyPatch/mappedPatchBaseI.H | 25 +++ .../mappedPatchBaseTemplates.C | 44 +++- .../nonConformalCyclicPolyPatch.H | 4 +- .../intersection/intersectionPatchToPatch.C | 207 ++++++++++-------- .../intersection/intersectionPatchToPatch.H | 32 ++- .../inverseDistancePatchToPatch.C | 43 ++-- .../inverseDistancePatchToPatch.H | 27 +-- .../matching/matchingPatchToPatch.C | 163 ++++++++++++++ .../matching/matchingPatchToPatch.H | 97 ++++++++ .../nearest/nearestPatchToPatch.C | 41 ++-- .../nearest/nearestPatchToPatch.H | 29 +-- .../patchToPatch/patchToPatch/patchToPatch.C | 36 ++- .../patchToPatch/patchToPatch/patchToPatch.H | 124 +++++++---- .../patchToPatch/patchToPatchParallelOps.C | 98 +-------- .../patchToPatch/patchToPatchTemplates.C | 201 +++++++++++++++++ .../patchToPatch/rays/raysPatchToPatch.C | 43 ++-- .../patchToPatch/rays/raysPatchToPatch.H | 27 +-- .../thermalBaffleFvPatchScalarField.C | 2 +- 22 files changed, 931 insertions(+), 406 deletions(-) create mode 100644 src/meshTools/patchToPatch/matching/matchingPatchToPatch.C create mode 100644 src/meshTools/patchToPatch/matching/matchingPatchToPatch.H create mode 100644 src/meshTools/patchToPatch/patchToPatch/patchToPatchTemplates.C diff --git a/src/functionObjects/field/nearWallFields/nearWallFields.C b/src/functionObjects/field/nearWallFields/nearWallFields.C index 4b1fa93d55..7d4861e1be 100644 --- a/src/functionObjects/field/nearWallFields/nearWallFields.C +++ b/src/functionObjects/field/nearWallFields/nearWallFields.C @@ -26,7 +26,6 @@ License #include "nearWallFields.H" #include "wordReList.H" #include "findCellParticle.H" -#include "mappedPatchBase.H" #include "OBJstream.H" #include "addToRunTimeSelectionTable.H" diff --git a/src/meshTools/Make/files b/src/meshTools/Make/files index f0338596e3..725051f87a 100644 --- a/src/meshTools/Make/files +++ b/src/meshTools/Make/files @@ -242,6 +242,7 @@ $(AMICycPatches)/cyclicAMIPointPatchField/cyclicAMIPointPatchFields.C patchToPatch/patchToPatch/patchToPatch.C patchToPatch/patchToPatch/patchToPatchParallelOps.C +patchToPatch/matching/matchingPatchToPatch.C patchToPatch/nearest/nearestPatchToPatch.C patchToPatch/inverseDistance/inverseDistancePatchToPatch.C patchToPatch/intersection/intersectionPatchToPatch.C diff --git a/src/meshTools/mappedPatches/mappedPolyPatch/mappedPatchBase.C b/src/meshTools/mappedPatches/mappedPolyPatch/mappedPatchBase.C index 729b4fb004..306401d827 100644 --- a/src/meshTools/mappedPatches/mappedPolyPatch/mappedPatchBase.C +++ b/src/meshTools/mappedPatches/mappedPolyPatch/mappedPatchBase.C @@ -37,6 +37,7 @@ License #include "distributionMap.H" #include "triPointRef.H" #include "RemoteData.H" +#include "intersectionPatchToPatch.H" #include "addToRunTimeSelectionTable.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -49,12 +50,13 @@ namespace Foam const char* Foam::NamedEnum < Foam::mappedPatchBase::sampleMode, - 4 + 5 >::names[] = { "nearestCell", "nearestPatchFace", "nearestPatchFaceAMI", + "patchToPatch", "nearestFace" }; @@ -72,7 +74,7 @@ namespace Foam } -const Foam::NamedEnum +const Foam::NamedEnum Foam::mappedPatchBase::sampleModeNames_; const Foam::NamedEnum @@ -272,6 +274,11 @@ void Foam::mappedPatchBase::findSamples { break; } + + case PATCHTOPATCH: + { + break; + } } // Find nearest. Combine on master. @@ -379,6 +386,10 @@ Foam::label Foam::mappedPatchBase::sampleSize() const { return samplePolyPatch().size(); } + case PATCHTOPATCH: + { + return samplePolyPatch().size(); + } case NEARESTFACE: { return sampleMesh().nFaces() - sampleMesh().nInternalFaces(); @@ -539,6 +550,25 @@ void Foam::mappedPatchBase::calcAMI() const } +void Foam::mappedPatchBase::calcPatchToPatch() const +{ + if (patchToPatchIsValid_) + { + FatalErrorInFunction + << "Patch-to-patch already calculated" << exit(FatalError); + } + + patchToPatchPtr_->update + ( + patch_, + patch_.pointNormals(), + samplePolyPatch() + ); + + patchToPatchIsValid_ = true; +} + + // Hack to read old (List-based) format. See Field.C. The difference // is only that in case of falling back to old format it expects a non-uniform // list instead of a single vector. @@ -630,7 +660,9 @@ Foam::mappedPatchBase::mappedPatchBase AMIPtr_(nullptr), AMIReverse_(false), surfPtr_(nullptr), - surfDict_(fileName("surface")) + surfDict_(fileName("surface")), + patchToPatchIsValid_(false), + patchToPatchPtr_(nullptr) {} @@ -656,7 +688,14 @@ Foam::mappedPatchBase::mappedPatchBase AMIPtr_(nullptr), AMIReverse_(false), surfPtr_(nullptr), - surfDict_(fileName("surface")) + surfDict_(fileName("surface")), + patchToPatchIsValid_(false), + patchToPatchPtr_ + ( + mode == PATCHTOPATCH + ? new patchToPatches::intersection(false) + : nullptr + ) {} @@ -690,7 +729,14 @@ Foam::mappedPatchBase::mappedPatchBase AMIPtr_(nullptr), AMIReverse_(dict.lookupOrDefault("flipNormals", false)), surfPtr_(nullptr), - surfDict_(dict.subOrEmptyDict("surface")) + surfDict_(dict.subOrEmptyDict("surface")), + patchToPatchIsValid_(false), + patchToPatchPtr_ + ( + mode_ == PATCHTOPATCH + ? patchToPatch::New(dict.lookup("patchToPatchMode"), false) + : autoPtr(nullptr) + ) { if (!coupleGroup_.valid() && sampleRegion_.empty()) { @@ -721,7 +767,14 @@ Foam::mappedPatchBase::mappedPatchBase AMIPtr_(nullptr), AMIReverse_(mpb.AMIReverse_), surfPtr_(nullptr), - surfDict_(mpb.surfDict_) + surfDict_(mpb.surfDict_), + patchToPatchIsValid_(false), + patchToPatchPtr_ + ( + mode_ == PATCHTOPATCH + ? patchToPatch::New(mpb.patchToPatchPtr_->type(), false) + : autoPtr(nullptr) + ) {} @@ -886,6 +939,11 @@ void Foam::mappedPatchBase::write(Ostream& os) const os << surfDict_; } } + + if (mode_ == PATCHTOPATCH) + { + writeEntry(os, "patchToPatchMode", patchToPatchPtr_->type()); + } } diff --git a/src/meshTools/mappedPatches/mappedPolyPatch/mappedPatchBase.H b/src/meshTools/mappedPatches/mappedPolyPatch/mappedPatchBase.H index 2e5146464a..299bf59384 100644 --- a/src/meshTools/mappedPatches/mappedPolyPatch/mappedPatchBase.H +++ b/src/meshTools/mappedPatches/mappedPolyPatch/mappedPatchBase.H @@ -77,6 +77,7 @@ SourceFiles #include "pointField.H" #include "AMIInterpolation.H" +#include "patchToPatch.H" #include "coupleGroupIdentifier.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -105,6 +106,7 @@ public: NEARESTCELL, // nearest cell containing sample NEARESTPATCHFACE, // nearest face on selected patch NEARESTPATCHFACEAMI, // nearest patch face + AMI interpolation + PATCHTOPATCH, // ... NEARESTFACE // nearest face }; @@ -116,7 +118,7 @@ public: DIRECTION // offset with a specified vector }; - static const NamedEnum sampleModeNames_; + static const NamedEnum sampleModeNames_; static const NamedEnum offsetModeNames_; @@ -177,6 +179,15 @@ protected: dictionary surfDict_; + //- Patch-to-patch intersection engine (only for PATCHTOPATCH) + + //- Is the patch-to-patch intersection engine up to date? + mutable bool patchToPatchIsValid_; + + //- Patch-to-patch intersection engine + mutable autoPtr patchToPatchPtr_; + + // Protected Member Functions //- Read the offset mode from a dictionary @@ -199,6 +210,9 @@ protected: //- Calculate AMI interpolator void calcAMI() const; + //- Calculate the patch-to-patch intersection engine + void calcPatchToPatch() const; + //- Helper to read field or non-uniform list from dictionary static tmp readListOrField ( @@ -207,6 +221,12 @@ protected: const label size ); + //- Return whether or not the sample patch (if any) is of mapped type + inline bool sampleIsMappedPatch() const; + + //- Get the mapped sample patch + inline const mappedPatchBase& sampleMappedPatch() const; + public: diff --git a/src/meshTools/mappedPatches/mappedPolyPatch/mappedPatchBaseI.H b/src/meshTools/mappedPatches/mappedPolyPatch/mappedPatchBaseI.H index b26f5d6dde..96b3c0e5ec 100644 --- a/src/meshTools/mappedPatches/mappedPolyPatch/mappedPatchBaseI.H +++ b/src/meshTools/mappedPatches/mappedPolyPatch/mappedPatchBaseI.H @@ -25,6 +25,31 @@ License #include "mappedPatchBase.H" +// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * // + +inline bool Foam::mappedPatchBase::sampleIsMappedPatch() const +{ + switch (mode_) + { + case NEARESTCELL: + case NEARESTFACE: + return false; + case NEARESTPATCHFACE: + case NEARESTPATCHFACEAMI: + case PATCHTOPATCH: + return isA(samplePolyPatch()); + } + return false; +} + + +inline const Foam::mappedPatchBase& +Foam::mappedPatchBase::sampleMappedPatch() const +{ + return refCast(samplePolyPatch()); +} + + // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // inline const Foam::mappedPatchBase::sampleMode& diff --git a/src/meshTools/mappedPatches/mappedPolyPatch/mappedPatchBaseTemplates.C b/src/meshTools/mappedPatches/mappedPolyPatch/mappedPatchBaseTemplates.C index 011f3fe178..1342806c7b 100644 --- a/src/meshTools/mappedPatches/mappedPolyPatch/mappedPatchBaseTemplates.C +++ b/src/meshTools/mappedPatches/mappedPolyPatch/mappedPatchBaseTemplates.C @@ -41,6 +41,25 @@ Foam::mappedPatchBase::distribute(const Field& fld) const } return AMIPtr_->interpolateToSource(fld); } + case PATCHTOPATCH: + { + if + ( + !patchToPatchIsValid_ + && !( + sampleIsMappedPatch() + && sampleMappedPatch().patchToPatchIsValid_ + ) + ) + { + calcPatchToPatch(); + } + + return + patchToPatchIsValid_ + ? patchToPatchPtr_->tgtToSrc(fld) + : sampleMappedPatch().patchToPatchPtr_->srcToTgt(fld); + } default: { if (mapPtr_.empty()) @@ -91,12 +110,33 @@ Foam::mappedPatchBase::reverseDistribute(const Field& fld) const } return AMIPtr_->interpolateToTarget(fld); } + case PATCHTOPATCH: + { + if + ( + !patchToPatchIsValid_ + && !( + sampleIsMappedPatch() + && sampleMappedPatch().patchToPatchIsValid_ + ) + ) + { + calcPatchToPatch(); + } + + return + patchToPatchIsValid_ + ? patchToPatchPtr_->srcToTgt(fld) + : sampleMappedPatch().patchToPatchPtr_->tgtToSrc(fld); + + } default: { FatalErrorInFunction << "Reverse distribute can only be used in " - << sampleModeNames_[NEARESTPATCHFACE] << " or " - << sampleModeNames_[NEARESTPATCHFACEAMI] << "mode" + << sampleModeNames_[NEARESTPATCHFACE] << ", " + << sampleModeNames_[NEARESTPATCHFACEAMI] << " or " + << sampleModeNames_[PATCHTOPATCH] << " mode" << exit(FatalError); return tmp>(nullptr); diff --git a/src/meshTools/nonConformal/polyPatches/nonConformalCyclic/nonConformalCyclicPolyPatch.H b/src/meshTools/nonConformal/polyPatches/nonConformalCyclic/nonConformalCyclicPolyPatch.H index bd160dd7f6..288dafb120 100644 --- a/src/meshTools/nonConformal/polyPatches/nonConformalCyclic/nonConformalCyclicPolyPatch.H +++ b/src/meshTools/nonConformal/polyPatches/nonConformalCyclic/nonConformalCyclicPolyPatch.H @@ -68,10 +68,10 @@ protected: //- Patch-to-patch intersection engine mutable patchToPatches::intersection intersection_; - //- Is the intersection engine up to date? + //- Is the rays engine up to date? mutable bool raysIsValid_; - //- Patch-to-patch intersection engine + //- Patch-to-patch rays engine mutable patchToPatches::rays rays_; diff --git a/src/meshTools/patchToPatch/intersection/intersectionPatchToPatch.C b/src/meshTools/patchToPatch/intersection/intersectionPatchToPatch.C index 2891936565..e6f0ce5697 100644 --- a/src/meshTools/patchToPatch/intersection/intersectionPatchToPatch.C +++ b/src/meshTools/patchToPatch/intersection/intersectionPatchToPatch.C @@ -544,13 +544,12 @@ void Foam::patchToPatches::intersection::initialise void Foam::patchToPatches::intersection::rDistributeTgt ( - const primitiveOldTimePatch& tgtPatch, - const distributionMap& tgtMap + const primitiveOldTimePatch& tgtPatch ) { - patchToPatch::rDistributeTgt(tgtPatch, tgtMap); + patchToPatch::rDistributeTgt(tgtPatch); - rDistributeListList(tgtPatch.size(), tgtMap, tgtCouples_); + rDistributeListList(tgtPatch.size(), tgtMapPtr_(), tgtCouples_); } @@ -655,6 +654,44 @@ Foam::label Foam::patchToPatches::intersection::finalise } } + // Calculate coverage and total areas on both sides + auto coverage = [] + ( + const primitivePatch& patch, + const List>& couples, + scalar& area, + scalar& coupleArea, + List& coverage + ) + { + area = 0; + coupleArea = 0; + coverage.resize(patch.size()); + + forAll(patch, facei) + { + const scalar magA = mag(patch.faceAreas()[facei]); + + vector aCouple = Zero; + forAll(couples[facei], i) + { + aCouple += couples[facei][i].area; + } + const scalar magACouple = mag(aCouple); + + area += magA; + coupleArea += magACouple; + coverage[facei] = magACouple/magA; + } + + reduce(area, sumOp()); + reduce(coupleArea, sumOp()); + }; + scalar srcArea = 0, srcCoupleArea = 0; + scalar tgtArea = 0, tgtCoupleArea = 0; + coverage(srcPatch, srcCouples_, srcArea, srcCoupleArea, srcCoverage_); + coverage(tgtPatch, tgtCouples_, tgtArea, tgtCoupleArea, tgtCoverage_); + // Clear the triangulation workspace srcTriPoints_.clear(); srcTriFaceEdges_.clear(); @@ -669,8 +706,6 @@ Foam::label Foam::patchToPatches::intersection::finalise // Checking and reporting if (nCouples != 0) { - scalar srcArea = 0, srcCoupleArea = 0; - scalarField srcCoverage(srcPatch.size()); scalarField srcOpenness(srcPatch.size()); scalarField srcError(srcPatch.size()); scalarField srcDepth(srcPatch.size()); @@ -689,11 +724,6 @@ Foam::label Foam::patchToPatches::intersection::finalise Cpl += cpl; Cpl.nbr += cpl.nbr; } - const scalar magCA = mag(Cpl.area); - - srcArea += magA; - srcCoupleArea += magCA; - srcCoverage[srcFacei] = magCA/magA; vector projectionA = Zero; scalar projectionV = 0; @@ -736,36 +766,15 @@ Foam::label Foam::patchToPatches::intersection::finalise srcDepth[srcFacei] = mag(projectionV)/pow3(sqrt(magA)); } - reduce(srcArea, sumOp()); - reduce(srcCoupleArea, sumOp()); - - scalar tgtArea = 0, tgtCoupleArea = 0; - scalarField tgtCoverage(tgtPatch.size()); - forAll(tgtPatch, tgtFacei) - { - const scalar magA = mag(tgtPatch.faceAreas()[tgtFacei]); - - vector aCouple = Zero; - forAll(tgtCouples_[tgtFacei], tgtSrcFacei) - { - aCouple += tgtCouples_[tgtFacei][tgtSrcFacei].area; - } - const scalar magACouple = mag(aCouple); - - tgtArea += magA; - tgtCoupleArea += magACouple; - tgtCoverage[tgtFacei] = magACouple/magA; - } - reduce(tgtArea, sumOp()); reduce(tgtCoupleArea, sumOp()); Info<< indent << "Source min/average/max coverage = " - << gMin(srcCoverage) << '/' << srcCoupleArea/srcArea << '/' - << gMax(srcCoverage) << endl + << gMin(srcCoverage_) << '/' << srcCoupleArea/srcArea << '/' + << gMax(srcCoverage_) << endl << indent << "Target min/average/max coverage = " - << gMin(tgtCoverage) << '/' << tgtCoupleArea/tgtArea << '/' - << gMax(tgtCoverage) << endl + << gMin(tgtCoverage_) << '/' << tgtCoupleArea/tgtArea << '/' + << gMax(tgtCoverage_) << endl << indent << "Source average openness/error/depth/angle = " << gAverage(srcOpenness) << '/' << gAverage(srcError) << '/' << gAverage(srcDepth) << '/' << gAverage(srcAngle) << endl @@ -815,7 +824,7 @@ Foam::label Foam::patchToPatches::intersection::finalise labelList(), labelListList(), srcPatch.localFaces(), - "coverage", false, srcCoverage, + "coverage", false, scalarField(srcCoverage_), "openness", false, srcOpenness, "error", false, srcError, "depth", false, srcDepth, @@ -833,7 +842,7 @@ Foam::label Foam::patchToPatches::intersection::finalise labelList(), labelListList(), tgtPatch.localFaces(), - "coverage", false, tgtCoverage + "coverage", false, scalarField(tgtCoverage_) ); } } @@ -842,6 +851,68 @@ Foam::label Foam::patchToPatches::intersection::finalise } +Foam::tmpNrc>> +Foam::patchToPatches::intersection::srcWeights() const +{ + List>* resultPtr + ( + new List>(srcCouples_.size()) + ); + List>& result = *resultPtr; + + forAll(srcCouples_, srcFacei) + { + result[srcFacei].resize(srcCouples_[srcFacei].size()); + scalar aSum = 0; + + forAll(srcCouples_[srcFacei], i) + { + const scalar a = mag(srcCouples_[srcFacei][i].area); + result[srcFacei][i] = a; + aSum += a; + } + + forAll(srcCouples_[srcFacei], i) + { + result[srcFacei][i] *= srcCoverage_[srcFacei]/aSum; + } + } + + return tmpNrc>>(resultPtr); +} + + +Foam::tmpNrc>> +Foam::patchToPatches::intersection::tgtWeights() const +{ + List>* resultPtr + ( + new List>(tgtCouples_.size()) + ); + List>& result = *resultPtr; + + forAll(tgtCouples_, tgtFacei) + { + result[tgtFacei].resize(tgtCouples_[tgtFacei].size()); + scalar aSum = 0; + + forAll(tgtCouples_[tgtFacei], i) + { + const scalar a = mag(tgtCouples_[tgtFacei][i].area); + result[tgtFacei][i] = a; + aSum += a; + } + + forAll(tgtCouples_[tgtFacei], i) + { + result[tgtFacei][i] *= tgtCoverage_[tgtFacei]/aSum; + } + } + + return tmpNrc>>(resultPtr); +} + + // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // Foam::patchToPatches::intersection::intersection(const bool reverse) @@ -849,9 +920,11 @@ Foam::patchToPatches::intersection::intersection(const bool reverse) patchToPatch(reverse), srcCouples_(), + srcCoverage_(), srcEdgeParts_(), srcErrorParts_(), tgtCouples_(), + tgtCoverage_(), triEngine_(), @@ -884,62 +957,4 @@ Foam::patchToPatches::intersection::~intersection() {} -// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // - -Foam::tmpNrc>> -Foam::patchToPatches::intersection::srcWeights -( - const primitivePatch& srcPatch -) const -{ - List>* resultPtr - ( - new List>(srcCouples_.size()) - ); - List>& result = *resultPtr; - - forAll(srcCouples_, srcFacei) - { - result[srcFacei].resize(srcCouples_[srcFacei].size()); - - const scalar magA = mag(srcPatch.faceAreas()[srcFacei]); - - forAll(srcCouples_[srcFacei], i) - { - result[srcFacei][i] = mag(srcCouples_[srcFacei][i].area)/magA; - } - } - - return tmpNrc>>(resultPtr); -} - - -Foam::tmpNrc>> -Foam::patchToPatches::intersection::tgtWeights -( - const primitivePatch& tgtPatch -) const -{ - List>* resultPtr - ( - new List>(tgtCouples_.size()) - ); - List>& result = *resultPtr; - - forAll(tgtCouples_, tgtFacei) - { - result[tgtFacei].resize(tgtCouples_[tgtFacei].size()); - - const scalar magA = mag(tgtPatch.faceAreas()[tgtFacei]); - - forAll(tgtCouples_[tgtFacei], i) - { - result[tgtFacei][i] = mag(tgtCouples_[tgtFacei][i].area)/magA; - } - } - - return tmpNrc>>(resultPtr); -} - - // ************************************************************************* // diff --git a/src/meshTools/patchToPatch/intersection/intersectionPatchToPatch.H b/src/meshTools/patchToPatch/intersection/intersectionPatchToPatch.H index a9e14ace17..2dce50493d 100644 --- a/src/meshTools/patchToPatch/intersection/intersectionPatchToPatch.H +++ b/src/meshTools/patchToPatch/intersection/intersectionPatchToPatch.H @@ -75,7 +75,7 @@ public: part() : area(Zero), - centre(point::uniform(NaN)) + centre(NaN()) {} //- Default construct @@ -210,6 +210,9 @@ private: //- The coupling geometry for for each source face List> srcCouples_; + //- The proportion of the source faces that are coupled + List srcCoverage_; + //- The non-coupled geometry associated with each source edge List srcEdgeParts_; @@ -220,6 +223,9 @@ private: //- The coupling geometry for for each target face List> tgtCouples_; + //- The proportion of the target faces that are coupled + List tgtCoverage_; + //- Triangulation engine mutable polygonTriangulate triEngine_; @@ -325,11 +331,7 @@ private: //- Send data that resulted from an intersection between the source // patch and a distributed source-local-target patch back to the // original target processes. - virtual void rDistributeTgt - ( - const primitiveOldTimePatch& tgtPatch, - const distributionMap& tgtMap - ); + virtual void rDistributeTgt(const primitiveOldTimePatch& tgtPatch); //- Finalise the intersection virtual label finalise @@ -341,6 +343,12 @@ private: const transformer& tgtToSrc ); + //- For each source face, the coupled target weights + virtual tmpNrc>> srcWeights() const; + + //- For each target face, the coupled source weights + virtual tmpNrc>> tgtWeights() const; + public: @@ -393,18 +401,6 @@ public: //- For each target face, the target and source areas for each // source coupling inline const List>& tgtCouples() const; - - //- For each source face, the coupled target weights - virtual tmpNrc>> srcWeights - ( - const primitivePatch& srcPatch - ) const; - - //- For each target face, the coupled source weights - virtual tmpNrc>> tgtWeights - ( - const primitivePatch& tgtPatch - ) const; }; diff --git a/src/meshTools/patchToPatch/inverseDistance/inverseDistancePatchToPatch.C b/src/meshTools/patchToPatch/inverseDistance/inverseDistancePatchToPatch.C index 0ba290ab6e..fa4e0ff5a3 100644 --- a/src/meshTools/patchToPatch/inverseDistance/inverseDistancePatchToPatch.C +++ b/src/meshTools/patchToPatch/inverseDistance/inverseDistancePatchToPatch.C @@ -190,13 +190,12 @@ void Foam::patchToPatches::inverseDistance::initialise void Foam::patchToPatches::inverseDistance::rDistributeTgt ( - const primitiveOldTimePatch& tgtPatch, - const distributionMap& tgtMap + const primitiveOldTimePatch& tgtPatch ) { - patchToPatch::rDistributeTgt(tgtPatch, tgtMap); + patchToPatch::rDistributeTgt(tgtPatch); - rDistributeListList(tgtPatch.size(), tgtMap, tgtWeights_); + rDistributeListList(tgtPatch.size(), tgtMapPtr_(), tgtWeights_); } @@ -243,6 +242,20 @@ Foam::label Foam::patchToPatches::inverseDistance::finalise } +Foam::tmpNrc>> +Foam::patchToPatches::inverseDistance::srcWeights() const +{ + return srcWeights_; +} + + +Foam::tmpNrc>> +Foam::patchToPatches::inverseDistance::tgtWeights() const +{ + return tgtWeights_; +} + + // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // Foam::patchToPatches::inverseDistance::inverseDistance(const bool reverse) @@ -259,26 +272,4 @@ Foam::patchToPatches::inverseDistance::~inverseDistance() {} -// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // - -Foam::tmpNrc>> -Foam::patchToPatches::inverseDistance::srcWeights -( - const primitivePatch& srcPatch -) const -{ - return srcWeights_; -} - - -Foam::tmpNrc>> -Foam::patchToPatches::inverseDistance::tgtWeights -( - const primitivePatch& tgtPatch -) const -{ - return tgtWeights_; -} - - // ************************************************************************* // diff --git a/src/meshTools/patchToPatch/inverseDistance/inverseDistancePatchToPatch.H b/src/meshTools/patchToPatch/inverseDistance/inverseDistancePatchToPatch.H index fe650274fb..a18d96a878 100644 --- a/src/meshTools/patchToPatch/inverseDistance/inverseDistancePatchToPatch.H +++ b/src/meshTools/patchToPatch/inverseDistance/inverseDistancePatchToPatch.H @@ -117,11 +117,7 @@ class inverseDistance //- Send data that resulted from an intersection between the source // patch and a distributed source-local-target patch back to the // original target processes. - virtual void rDistributeTgt - ( - const primitiveOldTimePatch& tgtPatch, - const distributionMap& tgtMap - ); + virtual void rDistributeTgt(const primitiveOldTimePatch& tgtPatch); //- Finalise the intersection virtual label finalise @@ -133,6 +129,12 @@ class inverseDistance const transformer& tgtToSrc ); + //- For each source face, the coupled target weights + virtual tmpNrc>> srcWeights() const; + + //- For each target face, the coupled source weights + virtual tmpNrc>> tgtWeights() const; + public: @@ -148,21 +150,6 @@ public: //- Destructor ~inverseDistance(); - - - // Member Functions - - //- For each source face, the coupled target weights - virtual tmpNrc>> srcWeights - ( - const primitivePatch& srcPatch - ) const; - - //- For each target face, the coupled source weights - virtual tmpNrc>> tgtWeights - ( - const primitivePatch& tgtPatch - ) const; }; diff --git a/src/meshTools/patchToPatch/matching/matchingPatchToPatch.C b/src/meshTools/patchToPatch/matching/matchingPatchToPatch.C new file mode 100644 index 0000000000..7f6f663240 --- /dev/null +++ b/src/meshTools/patchToPatch/matching/matchingPatchToPatch.C @@ -0,0 +1,163 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | Website: https://openfoam.org + \\ / A nd | Copyright (C) 2021-2022 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 "matchingPatchToPatch.H" +#include "addToRunTimeSelectionTable.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ +namespace patchToPatches +{ + defineTypeNameAndDebug(matching, 0); + addToRunTimeSelectionTable(patchToPatch, matching, bool); +} +} + + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +Foam::label Foam::patchToPatches::matching::finalise +( + const primitiveOldTimePatch& srcPatch, + const vectorField& srcPointNormals, + const vectorField& srcPointNormals0, + const primitiveOldTimePatch& tgtPatch, + const transformer& tgtToSrc +) +{ + const label nCouples = + nearest::finalise + ( + srcPatch, + srcPointNormals, + srcPointNormals0, + tgtPatch, + tgtToSrc + ); + + // Make sure every face references exactly one face + auto forwardCheck = [] + ( + const primitiveOldTimePatch& patch, + const List>& localOtherFaces, + const bool isSrc + ) + { + forAll(localOtherFaces, facei) + { + if (localOtherFaces[facei].size() != 1) + { + FatalErrorInFunction + << (isSrc ? "Source" : "Target") + << " face #" << facei << " at " + << patch.faceCentres()[facei] + << " did not match a face on the " + << (isSrc ? "target" : "source") + << " side" << exit(FatalError); + } + } + }; + forwardCheck(srcPatch, srcLocalTgtFaces_, true); + forwardCheck(tgtPatch, tgtLocalSrcFaces_, false); + + // Make sure every face is referenced by exactly one face + auto reverseCheck = [] + ( + const primitiveOldTimePatch& patch, + const List>& otherLocalFaces, + const autoPtr& mapPtr, + const bool isSrc + ) + { + labelList count + ( + mapPtr.valid() ? mapPtr->constructSize() : patch.size(), + 0 + ); + + forAll(otherLocalFaces, otherFacei) + { + forAll(otherLocalFaces[otherFacei], i) + { + count[otherLocalFaces[otherFacei][i]] ++; + } + } + + if (mapPtr.valid()) + { + distributionMapBase::distribute + ( + Pstream::commsTypes::nonBlocking, + List(), + patch.size(), + mapPtr->constructMap(), + false, + mapPtr->subMap(), + false, + count, + plusEqOp