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.
This commit is contained in:
Will Bainbridge
2022-09-01 08:31:16 +01:00
parent 7c5e2642a6
commit d1b53557e2
22 changed files with 931 additions and 406 deletions

View File

@ -26,7 +26,6 @@ License
#include "nearWallFields.H" #include "nearWallFields.H"
#include "wordReList.H" #include "wordReList.H"
#include "findCellParticle.H" #include "findCellParticle.H"
#include "mappedPatchBase.H"
#include "OBJstream.H" #include "OBJstream.H"
#include "addToRunTimeSelectionTable.H" #include "addToRunTimeSelectionTable.H"

View File

@ -242,6 +242,7 @@ $(AMICycPatches)/cyclicAMIPointPatchField/cyclicAMIPointPatchFields.C
patchToPatch/patchToPatch/patchToPatch.C patchToPatch/patchToPatch/patchToPatch.C
patchToPatch/patchToPatch/patchToPatchParallelOps.C patchToPatch/patchToPatch/patchToPatchParallelOps.C
patchToPatch/matching/matchingPatchToPatch.C
patchToPatch/nearest/nearestPatchToPatch.C patchToPatch/nearest/nearestPatchToPatch.C
patchToPatch/inverseDistance/inverseDistancePatchToPatch.C patchToPatch/inverseDistance/inverseDistancePatchToPatch.C
patchToPatch/intersection/intersectionPatchToPatch.C patchToPatch/intersection/intersectionPatchToPatch.C

View File

@ -37,6 +37,7 @@ License
#include "distributionMap.H" #include "distributionMap.H"
#include "triPointRef.H" #include "triPointRef.H"
#include "RemoteData.H" #include "RemoteData.H"
#include "intersectionPatchToPatch.H"
#include "addToRunTimeSelectionTable.H" #include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -49,12 +50,13 @@ namespace Foam
const char* Foam::NamedEnum const char* Foam::NamedEnum
< <
Foam::mappedPatchBase::sampleMode, Foam::mappedPatchBase::sampleMode,
4 5
>::names[] = >::names[] =
{ {
"nearestCell", "nearestCell",
"nearestPatchFace", "nearestPatchFace",
"nearestPatchFaceAMI", "nearestPatchFaceAMI",
"patchToPatch",
"nearestFace" "nearestFace"
}; };
@ -72,7 +74,7 @@ namespace Foam
} }
const Foam::NamedEnum<Foam::mappedPatchBase::sampleMode, 4> const Foam::NamedEnum<Foam::mappedPatchBase::sampleMode, 5>
Foam::mappedPatchBase::sampleModeNames_; Foam::mappedPatchBase::sampleModeNames_;
const Foam::NamedEnum<Foam::mappedPatchBase::offsetMode, 3> const Foam::NamedEnum<Foam::mappedPatchBase::offsetMode, 3>
@ -272,6 +274,11 @@ void Foam::mappedPatchBase::findSamples
{ {
break; break;
} }
case PATCHTOPATCH:
{
break;
}
} }
// Find nearest. Combine on master. // Find nearest. Combine on master.
@ -379,6 +386,10 @@ Foam::label Foam::mappedPatchBase::sampleSize() const
{ {
return samplePolyPatch().size(); return samplePolyPatch().size();
} }
case PATCHTOPATCH:
{
return samplePolyPatch().size();
}
case NEARESTFACE: case NEARESTFACE:
{ {
return sampleMesh().nFaces() - sampleMesh().nInternalFaces(); 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 // 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 // is only that in case of falling back to old format it expects a non-uniform
// list instead of a single vector. // list instead of a single vector.
@ -630,7 +660,9 @@ Foam::mappedPatchBase::mappedPatchBase
AMIPtr_(nullptr), AMIPtr_(nullptr),
AMIReverse_(false), AMIReverse_(false),
surfPtr_(nullptr), surfPtr_(nullptr),
surfDict_(fileName("surface")) surfDict_(fileName("surface")),
patchToPatchIsValid_(false),
patchToPatchPtr_(nullptr)
{} {}
@ -656,7 +688,14 @@ Foam::mappedPatchBase::mappedPatchBase
AMIPtr_(nullptr), AMIPtr_(nullptr),
AMIReverse_(false), AMIReverse_(false),
surfPtr_(nullptr), 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), AMIPtr_(nullptr),
AMIReverse_(dict.lookupOrDefault<bool>("flipNormals", false)), AMIReverse_(dict.lookupOrDefault<bool>("flipNormals", false)),
surfPtr_(nullptr), surfPtr_(nullptr),
surfDict_(dict.subOrEmptyDict("surface")) surfDict_(dict.subOrEmptyDict("surface")),
patchToPatchIsValid_(false),
patchToPatchPtr_
(
mode_ == PATCHTOPATCH
? patchToPatch::New(dict.lookup("patchToPatchMode"), false)
: autoPtr<patchToPatch>(nullptr)
)
{ {
if (!coupleGroup_.valid() && sampleRegion_.empty()) if (!coupleGroup_.valid() && sampleRegion_.empty())
{ {
@ -721,7 +767,14 @@ Foam::mappedPatchBase::mappedPatchBase
AMIPtr_(nullptr), AMIPtr_(nullptr),
AMIReverse_(mpb.AMIReverse_), AMIReverse_(mpb.AMIReverse_),
surfPtr_(nullptr), surfPtr_(nullptr),
surfDict_(mpb.surfDict_) surfDict_(mpb.surfDict_),
patchToPatchIsValid_(false),
patchToPatchPtr_
(
mode_ == PATCHTOPATCH
? patchToPatch::New(mpb.patchToPatchPtr_->type(), false)
: autoPtr<patchToPatch>(nullptr)
)
{} {}
@ -886,6 +939,11 @@ void Foam::mappedPatchBase::write(Ostream& os) const
os << surfDict_; os << surfDict_;
} }
} }
if (mode_ == PATCHTOPATCH)
{
writeEntry(os, "patchToPatchMode", patchToPatchPtr_->type());
}
} }

View File

@ -77,6 +77,7 @@ SourceFiles
#include "pointField.H" #include "pointField.H"
#include "AMIInterpolation.H" #include "AMIInterpolation.H"
#include "patchToPatch.H"
#include "coupleGroupIdentifier.H" #include "coupleGroupIdentifier.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -105,6 +106,7 @@ public:
NEARESTCELL, // nearest cell containing sample NEARESTCELL, // nearest cell containing sample
NEARESTPATCHFACE, // nearest face on selected patch NEARESTPATCHFACE, // nearest face on selected patch
NEARESTPATCHFACEAMI, // nearest patch face + AMI interpolation NEARESTPATCHFACEAMI, // nearest patch face + AMI interpolation
PATCHTOPATCH, // ...
NEARESTFACE // nearest face NEARESTFACE // nearest face
}; };
@ -116,7 +118,7 @@ public:
DIRECTION // offset with a specified vector DIRECTION // offset with a specified vector
}; };
static const NamedEnum<sampleMode, 4> sampleModeNames_; static const NamedEnum<sampleMode, 5> sampleModeNames_;
static const NamedEnum<offsetMode, 3> offsetModeNames_; static const NamedEnum<offsetMode, 3> offsetModeNames_;
@ -177,6 +179,15 @@ protected:
dictionary surfDict_; 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<patchToPatch> patchToPatchPtr_;
// Protected Member Functions // Protected Member Functions
//- Read the offset mode from a dictionary //- Read the offset mode from a dictionary
@ -199,6 +210,9 @@ protected:
//- Calculate AMI interpolator //- Calculate AMI interpolator
void calcAMI() const; void calcAMI() const;
//- Calculate the patch-to-patch intersection engine
void calcPatchToPatch() const;
//- Helper to read field or non-uniform list from dictionary //- Helper to read field or non-uniform list from dictionary
static tmp<pointField> readListOrField static tmp<pointField> readListOrField
( (
@ -207,6 +221,12 @@ protected:
const label size 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: public:

View File

@ -25,6 +25,31 @@ License
#include "mappedPatchBase.H" #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<mappedPatchBase>(samplePolyPatch());
}
return false;
}
inline const Foam::mappedPatchBase&
Foam::mappedPatchBase::sampleMappedPatch() const
{
return refCast<const mappedPatchBase>(samplePolyPatch());
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
inline const Foam::mappedPatchBase::sampleMode& inline const Foam::mappedPatchBase::sampleMode&

View File

@ -41,6 +41,25 @@ Foam::mappedPatchBase::distribute(const Field<Type>& fld) const
} }
return AMIPtr_->interpolateToSource(fld); return AMIPtr_->interpolateToSource(fld);
} }
case PATCHTOPATCH:
{
if
(
!patchToPatchIsValid_
&& !(
sampleIsMappedPatch()
&& sampleMappedPatch().patchToPatchIsValid_
)
)
{
calcPatchToPatch();
}
return
patchToPatchIsValid_
? patchToPatchPtr_->tgtToSrc(fld)
: sampleMappedPatch().patchToPatchPtr_->srcToTgt(fld);
}
default: default:
{ {
if (mapPtr_.empty()) if (mapPtr_.empty())
@ -91,12 +110,33 @@ Foam::mappedPatchBase::reverseDistribute(const Field<Type>& fld) const
} }
return AMIPtr_->interpolateToTarget(fld); return AMIPtr_->interpolateToTarget(fld);
} }
case PATCHTOPATCH:
{
if
(
!patchToPatchIsValid_
&& !(
sampleIsMappedPatch()
&& sampleMappedPatch().patchToPatchIsValid_
)
)
{
calcPatchToPatch();
}
return
patchToPatchIsValid_
? patchToPatchPtr_->srcToTgt(fld)
: sampleMappedPatch().patchToPatchPtr_->tgtToSrc(fld);
}
default: default:
{ {
FatalErrorInFunction FatalErrorInFunction
<< "Reverse distribute can only be used in " << "Reverse distribute can only be used in "
<< sampleModeNames_[NEARESTPATCHFACE] << " or " << sampleModeNames_[NEARESTPATCHFACE] << ", "
<< sampleModeNames_[NEARESTPATCHFACEAMI] << "mode" << sampleModeNames_[NEARESTPATCHFACEAMI] << " or "
<< sampleModeNames_[PATCHTOPATCH] << " mode"
<< exit(FatalError); << exit(FatalError);
return tmp<Field<Type>>(nullptr); return tmp<Field<Type>>(nullptr);

View File

@ -68,10 +68,10 @@ protected:
//- Patch-to-patch intersection engine //- Patch-to-patch intersection engine
mutable patchToPatches::intersection intersection_; mutable patchToPatches::intersection intersection_;
//- Is the intersection engine up to date? //- Is the rays engine up to date?
mutable bool raysIsValid_; mutable bool raysIsValid_;
//- Patch-to-patch intersection engine //- Patch-to-patch rays engine
mutable patchToPatches::rays rays_; mutable patchToPatches::rays rays_;

View File

@ -544,13 +544,12 @@ void Foam::patchToPatches::intersection::initialise
void Foam::patchToPatches::intersection::rDistributeTgt void Foam::patchToPatches::intersection::rDistributeTgt
( (
const primitiveOldTimePatch& tgtPatch, const primitiveOldTimePatch& tgtPatch
const distributionMap& tgtMap
) )
{ {
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<DynamicList<couple>>& couples,
scalar& area,
scalar& coupleArea,
List<scalar>& 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<scalar>());
reduce(coupleArea, sumOp<scalar>());
};
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 // Clear the triangulation workspace
srcTriPoints_.clear(); srcTriPoints_.clear();
srcTriFaceEdges_.clear(); srcTriFaceEdges_.clear();
@ -669,8 +706,6 @@ Foam::label Foam::patchToPatches::intersection::finalise
// Checking and reporting // Checking and reporting
if (nCouples != 0) if (nCouples != 0)
{ {
scalar srcArea = 0, srcCoupleArea = 0;
scalarField srcCoverage(srcPatch.size());
scalarField srcOpenness(srcPatch.size()); scalarField srcOpenness(srcPatch.size());
scalarField srcError(srcPatch.size()); scalarField srcError(srcPatch.size());
scalarField srcDepth(srcPatch.size()); scalarField srcDepth(srcPatch.size());
@ -689,11 +724,6 @@ Foam::label Foam::patchToPatches::intersection::finalise
Cpl += cpl; Cpl += cpl;
Cpl.nbr += cpl.nbr; Cpl.nbr += cpl.nbr;
} }
const scalar magCA = mag(Cpl.area);
srcArea += magA;
srcCoupleArea += magCA;
srcCoverage[srcFacei] = magCA/magA;
vector projectionA = Zero; vector projectionA = Zero;
scalar projectionV = 0; scalar projectionV = 0;
@ -736,36 +766,15 @@ Foam::label Foam::patchToPatches::intersection::finalise
srcDepth[srcFacei] = mag(projectionV)/pow3(sqrt(magA)); srcDepth[srcFacei] = mag(projectionV)/pow3(sqrt(magA));
} }
reduce(srcArea, sumOp<scalar>());
reduce(srcCoupleArea, sumOp<scalar>());
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<scalar>()); reduce(tgtArea, sumOp<scalar>());
reduce(tgtCoupleArea, sumOp<scalar>()); reduce(tgtCoupleArea, sumOp<scalar>());
Info<< indent << "Source min/average/max coverage = " Info<< indent << "Source min/average/max coverage = "
<< gMin(srcCoverage) << '/' << srcCoupleArea/srcArea << '/' << gMin(srcCoverage_) << '/' << srcCoupleArea/srcArea << '/'
<< gMax(srcCoverage) << endl << gMax(srcCoverage_) << endl
<< indent << "Target min/average/max coverage = " << indent << "Target min/average/max coverage = "
<< gMin(tgtCoverage) << '/' << tgtCoupleArea/tgtArea << '/' << gMin(tgtCoverage_) << '/' << tgtCoupleArea/tgtArea << '/'
<< gMax(tgtCoverage) << endl << gMax(tgtCoverage_) << endl
<< indent << "Source average openness/error/depth/angle = " << indent << "Source average openness/error/depth/angle = "
<< gAverage(srcOpenness) << '/' << gAverage(srcError) << '/' << gAverage(srcOpenness) << '/' << gAverage(srcError) << '/'
<< gAverage(srcDepth) << '/' << gAverage(srcAngle) << endl << gAverage(srcDepth) << '/' << gAverage(srcAngle) << endl
@ -815,7 +824,7 @@ Foam::label Foam::patchToPatches::intersection::finalise
labelList(), labelList(),
labelListList(), labelListList(),
srcPatch.localFaces(), srcPatch.localFaces(),
"coverage", false, srcCoverage, "coverage", false, scalarField(srcCoverage_),
"openness", false, srcOpenness, "openness", false, srcOpenness,
"error", false, srcError, "error", false, srcError,
"depth", false, srcDepth, "depth", false, srcDepth,
@ -833,7 +842,7 @@ Foam::label Foam::patchToPatches::intersection::finalise
labelList(), labelList(),
labelListList(), labelListList(),
tgtPatch.localFaces(), tgtPatch.localFaces(),
"coverage", false, tgtCoverage "coverage", false, scalarField(tgtCoverage_)
); );
} }
} }
@ -842,6 +851,68 @@ Foam::label Foam::patchToPatches::intersection::finalise
} }
Foam::tmpNrc<Foam::List<Foam::DynamicList<Foam::scalar>>>
Foam::patchToPatches::intersection::srcWeights() const
{
List<DynamicList<scalar>>* resultPtr
(
new List<DynamicList<scalar>>(srcCouples_.size())
);
List<DynamicList<scalar>>& 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<List<DynamicList<scalar>>>(resultPtr);
}
Foam::tmpNrc<Foam::List<Foam::DynamicList<Foam::scalar>>>
Foam::patchToPatches::intersection::tgtWeights() const
{
List<DynamicList<scalar>>* resultPtr
(
new List<DynamicList<scalar>>(tgtCouples_.size())
);
List<DynamicList<scalar>>& 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<List<DynamicList<scalar>>>(resultPtr);
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::patchToPatches::intersection::intersection(const bool reverse) Foam::patchToPatches::intersection::intersection(const bool reverse)
@ -849,9 +920,11 @@ Foam::patchToPatches::intersection::intersection(const bool reverse)
patchToPatch(reverse), patchToPatch(reverse),
srcCouples_(), srcCouples_(),
srcCoverage_(),
srcEdgeParts_(), srcEdgeParts_(),
srcErrorParts_(), srcErrorParts_(),
tgtCouples_(), tgtCouples_(),
tgtCoverage_(),
triEngine_(), triEngine_(),
@ -884,62 +957,4 @@ Foam::patchToPatches::intersection::~intersection()
{} {}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::tmpNrc<Foam::List<Foam::DynamicList<Foam::scalar>>>
Foam::patchToPatches::intersection::srcWeights
(
const primitivePatch& srcPatch
) const
{
List<DynamicList<scalar>>* resultPtr
(
new List<DynamicList<scalar>>(srcCouples_.size())
);
List<DynamicList<scalar>>& 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<List<DynamicList<scalar>>>(resultPtr);
}
Foam::tmpNrc<Foam::List<Foam::DynamicList<Foam::scalar>>>
Foam::patchToPatches::intersection::tgtWeights
(
const primitivePatch& tgtPatch
) const
{
List<DynamicList<scalar>>* resultPtr
(
new List<DynamicList<scalar>>(tgtCouples_.size())
);
List<DynamicList<scalar>>& 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<List<DynamicList<scalar>>>(resultPtr);
}
// ************************************************************************* // // ************************************************************************* //

View File

@ -75,7 +75,7 @@ public:
part() part()
: :
area(Zero), area(Zero),
centre(point::uniform(NaN)) centre(NaN<point>())
{} {}
//- Default construct //- Default construct
@ -210,6 +210,9 @@ private:
//- The coupling geometry for for each source face //- The coupling geometry for for each source face
List<DynamicList<couple>> srcCouples_; List<DynamicList<couple>> srcCouples_;
//- The proportion of the source faces that are coupled
List<scalar> srcCoverage_;
//- The non-coupled geometry associated with each source edge //- The non-coupled geometry associated with each source edge
List<part> srcEdgeParts_; List<part> srcEdgeParts_;
@ -220,6 +223,9 @@ private:
//- The coupling geometry for for each target face //- The coupling geometry for for each target face
List<DynamicList<couple>> tgtCouples_; List<DynamicList<couple>> tgtCouples_;
//- The proportion of the target faces that are coupled
List<scalar> tgtCoverage_;
//- Triangulation engine //- Triangulation engine
mutable polygonTriangulate triEngine_; mutable polygonTriangulate triEngine_;
@ -325,11 +331,7 @@ private:
//- Send data that resulted from an intersection between the source //- Send data that resulted from an intersection between the source
// patch and a distributed source-local-target patch back to the // patch and a distributed source-local-target patch back to the
// original target processes. // original target processes.
virtual void rDistributeTgt virtual void rDistributeTgt(const primitiveOldTimePatch& tgtPatch);
(
const primitiveOldTimePatch& tgtPatch,
const distributionMap& tgtMap
);
//- Finalise the intersection //- Finalise the intersection
virtual label finalise virtual label finalise
@ -341,6 +343,12 @@ private:
const transformer& tgtToSrc const transformer& tgtToSrc
); );
//- For each source face, the coupled target weights
virtual tmpNrc<List<DynamicList<scalar>>> srcWeights() const;
//- For each target face, the coupled source weights
virtual tmpNrc<List<DynamicList<scalar>>> tgtWeights() const;
public: public:
@ -393,18 +401,6 @@ public:
//- For each target face, the target and source areas for each //- For each target face, the target and source areas for each
// source coupling // source coupling
inline const List<DynamicList<couple>>& tgtCouples() const; inline const List<DynamicList<couple>>& tgtCouples() const;
//- For each source face, the coupled target weights
virtual tmpNrc<List<DynamicList<scalar>>> srcWeights
(
const primitivePatch& srcPatch
) const;
//- For each target face, the coupled source weights
virtual tmpNrc<List<DynamicList<scalar>>> tgtWeights
(
const primitivePatch& tgtPatch
) const;
}; };

View File

@ -190,13 +190,12 @@ void Foam::patchToPatches::inverseDistance::initialise
void Foam::patchToPatches::inverseDistance::rDistributeTgt void Foam::patchToPatches::inverseDistance::rDistributeTgt
( (
const primitiveOldTimePatch& tgtPatch, const primitiveOldTimePatch& tgtPatch
const distributionMap& tgtMap
) )
{ {
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::List<Foam::DynamicList<Foam::scalar>>>
Foam::patchToPatches::inverseDistance::srcWeights() const
{
return srcWeights_;
}
Foam::tmpNrc<Foam::List<Foam::DynamicList<Foam::scalar>>>
Foam::patchToPatches::inverseDistance::tgtWeights() const
{
return tgtWeights_;
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::patchToPatches::inverseDistance::inverseDistance(const bool reverse) Foam::patchToPatches::inverseDistance::inverseDistance(const bool reverse)
@ -259,26 +272,4 @@ Foam::patchToPatches::inverseDistance::~inverseDistance()
{} {}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::tmpNrc<Foam::List<Foam::DynamicList<Foam::scalar>>>
Foam::patchToPatches::inverseDistance::srcWeights
(
const primitivePatch& srcPatch
) const
{
return srcWeights_;
}
Foam::tmpNrc<Foam::List<Foam::DynamicList<Foam::scalar>>>
Foam::patchToPatches::inverseDistance::tgtWeights
(
const primitivePatch& tgtPatch
) const
{
return tgtWeights_;
}
// ************************************************************************* // // ************************************************************************* //

View File

@ -117,11 +117,7 @@ class inverseDistance
//- Send data that resulted from an intersection between the source //- Send data that resulted from an intersection between the source
// patch and a distributed source-local-target patch back to the // patch and a distributed source-local-target patch back to the
// original target processes. // original target processes.
virtual void rDistributeTgt virtual void rDistributeTgt(const primitiveOldTimePatch& tgtPatch);
(
const primitiveOldTimePatch& tgtPatch,
const distributionMap& tgtMap
);
//- Finalise the intersection //- Finalise the intersection
virtual label finalise virtual label finalise
@ -133,6 +129,12 @@ class inverseDistance
const transformer& tgtToSrc const transformer& tgtToSrc
); );
//- For each source face, the coupled target weights
virtual tmpNrc<List<DynamicList<scalar>>> srcWeights() const;
//- For each target face, the coupled source weights
virtual tmpNrc<List<DynamicList<scalar>>> tgtWeights() const;
public: public:
@ -148,21 +150,6 @@ public:
//- Destructor //- Destructor
~inverseDistance(); ~inverseDistance();
// Member Functions
//- For each source face, the coupled target weights
virtual tmpNrc<List<DynamicList<scalar>>> srcWeights
(
const primitivePatch& srcPatch
) const;
//- For each target face, the coupled source weights
virtual tmpNrc<List<DynamicList<scalar>>> tgtWeights
(
const primitivePatch& tgtPatch
) const;
}; };

View File

@ -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 <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#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<DynamicList<label>>& 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<DynamicList<label>>& otherLocalFaces,
const autoPtr<distributionMap>& 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<labelPair>(),
patch.size(),
mapPtr->constructMap(),
false,
mapPtr->subMap(),
false,
count,
plusEqOp<label>(),
flipOp(),
label(0)
);
}
forAll(count, facei)
{
if (count[facei] != 1)
{
FatalErrorInFunction
<< (isSrc ? "Source" : "Target")
<< " face #" << facei << " at "
<< patch.faceCentres()[facei]
<< " did not match a face on the "
<< (isSrc ? "target" : "source")
<< " side" << exit(FatalError);
}
}
};
reverseCheck(srcPatch, tgtLocalSrcFaces_, srcMapPtr_, true);
reverseCheck(tgtPatch, srcLocalTgtFaces_, tgtMapPtr_, false);
return nCouples;
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::patchToPatches::matching::matching(const bool reverse)
:
nearest(reverse)
{}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::patchToPatches::matching::~matching()
{}
// ************************************************************************* //

View File

@ -0,0 +1,97 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 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 <http://www.gnu.org/licenses/>.
Class
Foam::patchToPatches::matching
Description
Class to generate patchToPatch coupling geometry. Couples a face to the
single matching opposite face only. This is functionally identical to the
nearest algorithm. It just adds some checking to ensure that the coupling
is perfectly one-to-one.
SourceFiles
matching.C
\*---------------------------------------------------------------------------*/
#ifndef matchingPatchToPatch_H
#define matchingPatchToPatch_H
#include "nearestPatchToPatch.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace patchToPatches
{
/*---------------------------------------------------------------------------*\
Class matching Declaration
\*---------------------------------------------------------------------------*/
class matching
:
public nearest
{
// Private Member Functions
//- Finalise the intersection
virtual label finalise
(
const primitiveOldTimePatch& srcPatch,
const vectorField& srcPointNormals,
const vectorField& srcPointNormals0,
const primitiveOldTimePatch& tgtPatch,
const transformer& tgtToSrc
);
public:
//- Runtime type information
TypeName("matching");
// Constructors
//- Construct from components
matching(const bool reverse);
//- Destructor
~matching();
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace patchToPatches
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -202,8 +202,7 @@ void Foam::patchToPatches::nearest::initialise
void Foam::patchToPatches::nearest::rDistributeTgt void Foam::patchToPatches::nearest::rDistributeTgt
( (
const primitiveOldTimePatch& tgtPatch, const primitiveOldTimePatch& tgtPatch
const distributionMap& tgtMap
) )
{ {
// Create a list-list of distances to match the addressing // Create a list-list of distances to match the addressing
@ -217,10 +216,10 @@ void Foam::patchToPatches::nearest::rDistributeTgt
} }
// Let the base class reverse distribute the addressing // Let the base class reverse distribute the addressing
patchToPatch::rDistributeTgt(tgtPatch, tgtMap); patchToPatch::rDistributeTgt(tgtPatch);
// Reverse distribute the distances // Reverse distribute the distances
rDistributeListList(tgtPatch.size(), tgtMap, tgtDistances); rDistributeListList(tgtPatch.size(), tgtMapPtr_(), tgtDistances);
// If there is more than one address, remove all but the closest // If there is more than one address, remove all but the closest
forAll(tgtLocalSrcFaces_, tgtFacei) forAll(tgtLocalSrcFaces_, tgtFacei)
@ -240,24 +239,8 @@ void Foam::patchToPatches::nearest::rDistributeTgt
} }
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::patchToPatches::nearest::nearest(const bool reverse)
:
patchToPatch(reverse)
{}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::patchToPatches::nearest::~nearest()
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::tmpNrc<Foam::List<Foam::DynamicList<Foam::scalar>>> Foam::tmpNrc<Foam::List<Foam::DynamicList<Foam::scalar>>>
Foam::patchToPatches::nearest::srcWeights(const primitivePatch& srcPatch) const Foam::patchToPatches::nearest::srcWeights() const
{ {
tmpNrc<List<DynamicList<scalar>>> tResult tmpNrc<List<DynamicList<scalar>>> tResult
( (
@ -279,7 +262,7 @@ Foam::patchToPatches::nearest::srcWeights(const primitivePatch& srcPatch) const
Foam::tmpNrc<Foam::List<Foam::DynamicList<Foam::scalar>>> Foam::tmpNrc<Foam::List<Foam::DynamicList<Foam::scalar>>>
Foam::patchToPatches::nearest::tgtWeights(const primitivePatch& tgtPatch) const Foam::patchToPatches::nearest::tgtWeights() const
{ {
tmpNrc<List<DynamicList<scalar>>> tResult tmpNrc<List<DynamicList<scalar>>> tResult
( (
@ -300,4 +283,18 @@ Foam::patchToPatches::nearest::tgtWeights(const primitivePatch& tgtPatch) const
} }
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::patchToPatches::nearest::nearest(const bool reverse)
:
patchToPatch(reverse)
{}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::patchToPatches::nearest::~nearest()
{}
// ************************************************************************* // // ************************************************************************* //

View File

@ -53,6 +53,8 @@ class nearest
: :
public patchToPatch public patchToPatch
{ {
protected:
// Private Member Data // Private Member Data
//- For each source face, the distance to its coupled target face //- For each source face, the distance to its coupled target face
@ -106,11 +108,13 @@ class nearest
//- Send data that resulted from an intersection between the source //- Send data that resulted from an intersection between the source
// patch and a distributed source-local-target patch back to the // patch and a distributed source-local-target patch back to the
// original target processes. // original target processes.
virtual void rDistributeTgt virtual void rDistributeTgt(const primitiveOldTimePatch& tgtPatch);
(
const primitiveOldTimePatch& tgtPatch, //- For each source face, the coupled target weights
const distributionMap& tgtMap virtual tmpNrc<List<DynamicList<scalar>>> srcWeights() const;
);
//- For each target face, the coupled source weights
virtual tmpNrc<List<DynamicList<scalar>>> tgtWeights() const;
public: public:
@ -127,21 +131,6 @@ public:
//- Destructor //- Destructor
~nearest(); ~nearest();
// Member Functions
//- For each source face, the coupled target weights
virtual tmpNrc<List<DynamicList<scalar>>> srcWeights
(
const primitivePatch& srcPatch
) const;
//- For each target face, the coupled source weights
virtual tmpNrc<List<DynamicList<scalar>>> tgtWeights
(
const primitivePatch& tgtPatch
) const;
}; };

View File

@ -714,11 +714,10 @@ Foam::patchToPatch::distributeTgt
const primitiveOldTimePatch& srcPatch, const primitiveOldTimePatch& srcPatch,
const vectorField& srcPointNormals, const vectorField& srcPointNormals,
const vectorField& srcPointNormals0, const vectorField& srcPointNormals0,
const primitiveOldTimePatch& tgtPatch, const primitiveOldTimePatch& tgtPatch
distributionMap& tgtMap
) )
{ {
tgtMap = tgtMapPtr_ =
patchDistributionMap patchDistributionMap
( (
tgtPatchSendFaces tgtPatchSendFaces
@ -740,7 +739,7 @@ Foam::patchToPatch::distributeTgt
( (
new PrimitiveOldTimePatch<faceList, pointField> new PrimitiveOldTimePatch<faceList, pointField>
( (
distributePatch(tgtMap, tgtPatch, localTgtProcFacesPtr_()) distributePatch(tgtMapPtr_(), tgtPatch, localTgtProcFacesPtr_())
) )
); );
} }
@ -749,11 +748,10 @@ Foam::patchToPatch::distributeTgt
Foam::tmpNrc<Foam::PrimitiveOldTimePatch<Foam::faceList, Foam::pointField>> Foam::tmpNrc<Foam::PrimitiveOldTimePatch<Foam::faceList, Foam::pointField>>
Foam::patchToPatch::distributeSrc Foam::patchToPatch::distributeSrc
( (
const primitiveOldTimePatch& srcPatch, const primitiveOldTimePatch& srcPatch
distributionMap& srcMap
) )
{ {
srcMap = patchDistributionMap(srcPatchSendFaces()); srcMapPtr_ = patchDistributionMap(srcPatchSendFaces());
if (localSrcProcFacesPtr_.empty()) if (localSrcProcFacesPtr_.empty())
{ {
@ -765,7 +763,7 @@ Foam::patchToPatch::distributeSrc
( (
new PrimitiveOldTimePatch<faceList, pointField> new PrimitiveOldTimePatch<faceList, pointField>
( (
distributePatch(srcMap, srcPatch, localSrcProcFacesPtr_()) distributePatch(srcMapPtr_(), srcPatch, localSrcProcFacesPtr_())
) )
); );
} }
@ -773,8 +771,7 @@ Foam::patchToPatch::distributeSrc
void Foam::patchToPatch::rDistributeTgt void Foam::patchToPatch::rDistributeTgt
( (
const primitiveOldTimePatch& tgtPatch, const primitiveOldTimePatch& tgtPatch
const distributionMap& tgtMap
) )
{ {
// Create a map from source procFace to local source face // Create a map from source procFace to local source face
@ -793,7 +790,7 @@ void Foam::patchToPatch::rDistributeTgt
List<List<procFace>> tgtSrcProcFaces = List<List<procFace>> tgtSrcProcFaces =
localFacesToProcFaces(tgtLocalSrcFaces_); localFacesToProcFaces(tgtLocalSrcFaces_);
rDistributeListList(tgtPatch.size(), tgtMap, tgtSrcProcFaces); rDistributeListList(tgtPatch.size(), tgtMapPtr_(), tgtSrcProcFaces);
tgtLocalSrcFaces_ = tgtLocalSrcFaces_ =
procFacesToLocalFaces(tgtSrcProcFaces, srcProcFaceToLocal); procFacesToLocalFaces(tgtSrcProcFaces, srcProcFaceToLocal);
@ -832,10 +829,12 @@ Foam::patchToPatch::patchToPatch(const bool reverse)
: :
reverse_(reverse), reverse_(reverse),
singleProcess_(-labelMax), singleProcess_(-labelMax),
localSrcProcFacesPtr_(nullptr),
localTgtProcFacesPtr_(nullptr),
srcLocalTgtFaces_(), srcLocalTgtFaces_(),
tgtLocalSrcFaces_() tgtLocalSrcFaces_(),
srcMapPtr_(nullptr),
tgtMapPtr_(nullptr),
localSrcProcFacesPtr_(nullptr),
localTgtProcFacesPtr_(nullptr)
{} {}
@ -965,15 +964,13 @@ void Foam::patchToPatch::update
else else
{ {
// Distribute the target // Distribute the target
distributionMap tgtMap;
tmpNrc<PrimitiveOldTimePatch<faceList, pointField>> localTTgtPatchPtr = tmpNrc<PrimitiveOldTimePatch<faceList, pointField>> localTTgtPatchPtr =
distributeTgt distributeTgt
( (
srcPatch, srcPatch,
srcPointNormals, srcPointNormals,
srcPointNormals0, srcPointNormals0,
tTgtPatch, tTgtPatch
tgtMap
); );
// Massage target patch into form that can be used by the serial // Massage target patch into form that can be used by the serial
@ -1008,12 +1005,11 @@ void Foam::patchToPatch::update
} }
// Distribute the source // Distribute the source
distributionMap srcMap;
tmpNrc<PrimitiveOldTimePatch<faceList, pointField>> localSrcPatchPtr = tmpNrc<PrimitiveOldTimePatch<faceList, pointField>> localSrcPatchPtr =
distributeSrc(srcPatch, srcMap); distributeSrc(srcPatch);
// Reverse distribute coupling data back to the target // Reverse distribute coupling data back to the target
rDistributeTgt(tgtPatch, tgtMap); rDistributeTgt(tgtPatch);
} }
// Finalise the intersection // Finalise the intersection

View File

@ -104,6 +104,18 @@ protected:
// if spread across multiple processors // if spread across multiple processors
label singleProcess_; label singleProcess_;
//- For each source face, the coupled local target faces
List<DynamicList<label>> srcLocalTgtFaces_;
//- For each target face, the coupled local source faces
List<DynamicList<label>> tgtLocalSrcFaces_;
//- Map from source patch faces to target-local source patch faces
autoPtr<distributionMap> srcMapPtr_;
//- Map from target patch faces to source-local target patch faces
autoPtr<distributionMap> tgtMapPtr_;
//- When running in parallel, a map from local source face index to //- When running in parallel, a map from local source face index to
// source processor and face index // source processor and face index
autoPtr<List<procFace>> localSrcProcFacesPtr_; autoPtr<List<procFace>> localSrcProcFacesPtr_;
@ -112,12 +124,6 @@ protected:
// target processor and face index // target processor and face index
autoPtr<List<procFace>> localTgtProcFacesPtr_; autoPtr<List<procFace>> localTgtProcFacesPtr_;
//- For each source face, the coupled local target faces
List<DynamicList<label>> srcLocalTgtFaces_;
//- For each target face, the coupled local source faces
List<DynamicList<label>> tgtLocalSrcFaces_;
// Private Member Functions // Private Member Functions
@ -285,19 +291,11 @@ protected:
//- Create a distribution map from a list-list of faces to be sent //- Create a distribution map from a list-list of faces to be sent
// (i.e., the result of calling one of the above methods). // (i.e., the result of calling one of the above methods).
distributionMap patchDistributionMap autoPtr<distributionMap> patchDistributionMap
( (
labelListList&& sendFaces labelListList&& sendFaces
) const; ) const;
//- Distribute a patch given its distribution map. Just generate
// local-proc-face addressing; not the distributed patch itself.
void distributePatch
(
const distributionMap& map,
List<procFace>& localProcFaces
) const;
//- Distribute a patch given its distribution map //- Distribute a patch given its distribution map
PrimitiveOldTimePatch<faceList, pointField> distributePatch PrimitiveOldTimePatch<faceList, pointField> distributePatch
( (
@ -321,8 +319,8 @@ protected:
//- Distribute the target patch so that enough is locally available //- Distribute the target patch so that enough is locally available
// for its intersection with the source patch can be computed. // for its intersection with the source patch can be computed.
// Happens before intersection. Bound boxes are used to determine // Happens before intersection. Bound boxes are used to determine
// what is needed where. Return the resulting local patch and the // what is needed where. Return the resulting local patch and
// map from which it was calculated. // internally set the target map.
virtual virtual
tmpNrc<PrimitiveOldTimePatch<faceList, pointField>> tmpNrc<PrimitiveOldTimePatch<faceList, pointField>>
distributeTgt distributeTgt
@ -330,31 +328,22 @@ protected:
const primitiveOldTimePatch& srcPatch, const primitiveOldTimePatch& srcPatch,
const vectorField& srcPointNormals, const vectorField& srcPointNormals,
const vectorField& srcPointNormals0, const vectorField& srcPointNormals0,
const primitiveOldTimePatch& tgtPatch, const primitiveOldTimePatch& tgtPatch
distributionMap& tgtMap
); );
//- Distribute the source patch so that everything the target //- Distribute the source patch so that everything the target
// intersects is locally available. Happens after intersection. // intersects is locally available. Happens after intersection.
// The intersection addressing is used to determine what is needed // The intersection addressing is used to determine what is needed
// where. Return the resulting local patch and the map from which // where. Return the resulting local patch and internally set the
// it was calculated. // source map.
virtual virtual
tmpNrc<PrimitiveOldTimePatch<faceList, pointField>> tmpNrc<PrimitiveOldTimePatch<faceList, pointField>>
distributeSrc distributeSrc(const primitiveOldTimePatch& srcPatch);
(
const primitiveOldTimePatch& srcPatch,
distributionMap& srcMap
);
//- Send data that resulted from an intersection between the source //- Send data that resulted from an intersection between the source
// patch and a distributed source-local-target patch back to the // patch and a distributed source-local-target patch back to the
// original target processes. // original target processes.
virtual void rDistributeTgt virtual void rDistributeTgt(const primitiveOldTimePatch& tgtPatch);
(
const primitiveOldTimePatch& tgtPatch,
const distributionMap& tgtMap
);
//- Finalising //- Finalising
virtual label finalise virtual label finalise
@ -367,6 +356,40 @@ protected:
); );
// Interpolation
//- For each source face, the coupled target weights
virtual tmpNrc<List<DynamicList<scalar>>> srcWeights() const = 0;
//- For each target face, the coupled source weights
virtual tmpNrc<List<DynamicList<scalar>>> tgtWeights() const = 0;
//- Return a primitive with all components set to NaN
template<class Type>
static Type NaN();
//- Interpolate with normalisation
template<class Type>
static tmp<Field<Type>> interpolate
(
const List<DynamicList<label>>& localOtherFaces,
const List<DynamicList<scalar>>& weights,
const autoPtr<distributionMap>& otherMapPtr,
const Field<Type>& otherFld
);
//- Interpolate without normalisation
template<class Type>
static tmp<Field<Type>> interpolate
(
const List<DynamicList<label>>& localOtherFaces,
const List<DynamicList<scalar>>& weights,
const autoPtr<distributionMap>& otherMapPtr,
const Field<Type>& otherFld,
const Field<Type>& leftOverFld
);
public: public:
//- Runtime type information //- Runtime type information
@ -428,17 +451,32 @@ public:
//- For each target face, the coupled source procs and faces //- For each target face, the coupled source procs and faces
inline List<List<procFace>> tgtSrcProcFaces() const; inline List<List<procFace>> tgtSrcProcFaces() const;
//- For each source face, the coupled target weights
virtual tmpNrc<List<DynamicList<scalar>>> srcWeights
(
const primitivePatch& srcPatch
) const = 0;
//- For each target face, the coupled source weights // Interpolation
virtual tmpNrc<List<DynamicList<scalar>>> tgtWeights
//- ...
template<class Type>
tmp<Field<Type>> srcToTgt(const Field<Type>& srcFld) const;
//- ...
template<class Type>
tmp<Field<Type>> srcToTgt
( (
const primitivePatch& tgtPatch const Field<Type>& srcFld,
) const = 0; const Field<Type>& leftOverTgtFld
) const;
//- ...
template<class Type>
tmp<Field<Type>> tgtToSrc(const Field<Type>& tgtFld) const;
//- ...
template<class Type>
tmp<Field<Type>> tgtToSrc
(
const Field<Type>& tgtFld,
const Field<Type>& leftOverSrcFld
) const;
// Manipulation // Manipulation
@ -480,6 +518,12 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "patchToPatchTemplates.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif #endif
// ************************************************************************* // // ************************************************************************* //

View File

@ -23,6 +23,7 @@ License
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#include "autoPtr.H"
#include "patchToPatch.H" #include "patchToPatch.H"
#include "treeBoundBoxList.H" #include "treeBoundBoxList.H"
#include "uindirectPrimitivePatch.H" #include "uindirectPrimitivePatch.H"
@ -153,7 +154,7 @@ Foam::labelListList Foam::patchToPatch::srcPatchSendFaces() const
} }
Foam::distributionMap Foam::patchToPatch::patchDistributionMap Foam::autoPtr<Foam::distributionMap> Foam::patchToPatch::patchDistributionMap
( (
labelListList&& sendFaces labelListList&& sendFaces
) const ) const
@ -204,99 +205,18 @@ Foam::distributionMap Foam::patchToPatch::patchDistributionMap
// Construct and return the map // Construct and return the map
return return
distributionMap autoPtr<distributionMap>
( (
localFacei, new distributionMap
move(sendFaces), (
move(receiveFaces) localFacei,
move(sendFaces),
move(receiveFaces)
)
); );
} }
void Foam::patchToPatch::distributePatch
(
const distributionMap& map,
List<procFace>& localProcFaces
) const
{
static const label thisProci = Pstream::myProcNo();
// Exchange per-processor data
List<labelList> procLocalFaceis(Pstream::nProcs());
{
PstreamBuffers pBufs(Pstream::commsTypes::nonBlocking);
// Send
for (label proci = 0; proci < Pstream::nProcs(); proci++)
{
const labelList& sendFaces = map.subMap()[proci];
if (proci != thisProci && sendFaces.size())
{
UOPstream(proci, pBufs)() << sendFaces;
}
}
pBufs.finishedSends();
// Map local data
{
const labelList& sendFaces = map.subMap()[thisProci];
procLocalFaceis[thisProci] = sendFaces;
}
// Receive remote data
for (label proci = 0; proci < Pstream::nProcs(); proci++)
{
const labelList& receiveNewFaces = map.constructMap()[proci];
if (proci != thisProci && receiveNewFaces.size())
{
UIPstream(proci, pBufs)() >> procLocalFaceis[proci];
}
}
}
// Allocate
{
label nLocalFaces = 0;
forAll(procLocalFaceis, proci)
{
nLocalFaces += procLocalFaceis[proci].size();
}
localProcFaces.setSize(nLocalFaces);
}
// Renumber and flatten
label localTgtFacei = 0;
// Local data first
{
const labelList& fis = procLocalFaceis[thisProci];
forAll(fis, i)
{
localProcFaces[localTgtFacei] = {thisProci, fis[i]};
localTgtFacei ++;
}
}
// Remote data after
forAll(procLocalFaceis, proci)
{
if (proci != thisProci)
{
const labelList& fis = procLocalFaceis[proci];
forAll(fis, i)
{
localProcFaces[localTgtFacei] = {proci, fis[i]};
localTgtFacei ++;
}
}
}
}
Foam::PrimitiveOldTimePatch<Foam::faceList, Foam::pointField> Foam::PrimitiveOldTimePatch<Foam::faceList, Foam::pointField>
Foam::patchToPatch::distributePatch Foam::patchToPatch::distributePatch
( (

View File

@ -0,0 +1,201 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 2011-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 <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "patchToPatch.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
template<class Type>
Type Foam::patchToPatch::NaN()
{
Type result;
for (direction cmpt = 0; cmpt < pTraits<Type>::nComponents; cmpt++)
{
setComponent(result, cmpt) = Foam::NaN;
}
return result;
}
template<class Type>
Foam::tmp<Foam::Field<Type>> Foam::patchToPatch::interpolate
(
const List<DynamicList<label>>& localOtherFaces,
const List<DynamicList<scalar>>& weights,
const autoPtr<distributionMap>& otherMapPtr,
const Field<Type>& otherFld
)
{
// Distribute the other field if necessary
tmp<Field<Type>> tLocalOtherFld;
if (otherMapPtr.valid())
{
tLocalOtherFld = tmp<Field<Type>>(new Field<Type>(otherFld));
otherMapPtr->distribute(tLocalOtherFld.ref());
}
const Field<Type>& localOtherFld =
otherMapPtr.valid() ? tLocalOtherFld() : otherFld;
// Allocate the result
tmp<Field<Type>> tFld(new Field<Type>(localOtherFaces.size(), NaN<Type>()));
Field<Type>& fld = tFld.ref();
// Compute the result as a weighted sum
forAll(localOtherFaces, tgtFacei)
{
scalar sumW = 0;
Type sumWF = Zero;
forAll(localOtherFaces[tgtFacei], i)
{
const scalar w = weights[tgtFacei][i];
sumW += w;
sumWF += w*localOtherFld[localOtherFaces[tgtFacei][i]];
}
if (localOtherFaces[tgtFacei].size())
{
fld[tgtFacei] = sumWF/sumW;
}
}
return tFld;
}
template<class Type>
Foam::tmp<Foam::Field<Type>> Foam::patchToPatch::interpolate
(
const List<DynamicList<label>>& localOtherFaces,
const List<DynamicList<scalar>>& weights,
const autoPtr<distributionMap>& otherMapPtr,
const Field<Type>& otherFld,
const Field<Type>& leftOverFld
)
{
// Distribute the other field if necessary
tmp<Field<Type>> tLocalOtherFld;
if (otherMapPtr.valid())
{
tLocalOtherFld = tmp<Field<Type>>(new Field<Type>(otherFld));
otherMapPtr->distribute(tLocalOtherFld.ref());
}
const Field<Type>& localOtherFld =
otherMapPtr.valid() ? tLocalOtherFld() : otherFld;
// Allocate the result
tmp<Field<Type>> tFld(new Field<Type>(localOtherFaces.size(), NaN<Type>()));
Field<Type>& fld = tFld.ref();
// Compute the result as a weighted sum
forAll(localOtherFaces, tgtFacei)
{
scalar sumW = 0;
Type sumWF = Zero;
forAll(localOtherFaces[tgtFacei], i)
{
const scalar w = weights[tgtFacei][i];
sumW += w;
sumWF += w*localOtherFld[localOtherFaces[tgtFacei][i]];
}
fld[tgtFacei] = sumWF + (1 - sumW)*leftOverFld[tgtFacei];
}
return tFld;
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class Type>
Foam::tmp<Foam::Field<Type>>
Foam::patchToPatch::srcToTgt(const Field<Type>& srcFld) const
{
return
interpolate
(
tgtLocalSrcFaces_,
tgtWeights(),
srcMapPtr_,
srcFld
);
}
template<class Type>
Foam::tmp<Foam::Field<Type>> Foam::patchToPatch::srcToTgt
(
const Field<Type>& srcFld,
const Field<Type>& leftOverTgtFld
) const
{
return
interpolate
(
tgtLocalSrcFaces_,
tgtWeights(),
srcMapPtr_,
srcFld,
leftOverTgtFld
);
}
template<class Type>
Foam::tmp<Foam::Field<Type>>
Foam::patchToPatch::tgtToSrc(const Field<Type>& tgtFld) const
{
return
interpolate
(
srcLocalTgtFaces_,
srcWeights(),
tgtMapPtr_,
tgtFld
);
}
template<class Type>
Foam::tmp<Foam::Field<Type>> Foam::patchToPatch::tgtToSrc
(
const Field<Type>& tgtFld,
const Field<Type>& leftOverSrcFld
) const
{
return
interpolate
(
srcLocalTgtFaces_,
srcWeights(),
tgtMapPtr_,
tgtFld,
leftOverSrcFld
);
}
// ************************************************************************* //

View File

@ -93,8 +93,7 @@ Foam::patchToPatches::rays::distributeTgt
const primitiveOldTimePatch& srcPatch, const primitiveOldTimePatch& srcPatch,
const vectorField& srcPointNormals, const vectorField& srcPointNormals,
const vectorField& srcPointNormals0, const vectorField& srcPointNormals0,
const primitiveOldTimePatch& tgtPatch, const primitiveOldTimePatch& tgtPatch
distributionMap& tgtMap
) )
{ {
// Intercept generation of the local patch. Store it. Return a const // Intercept generation of the local patch. Store it. Return a const
@ -106,8 +105,7 @@ Foam::patchToPatches::rays::distributeTgt
srcPatch, srcPatch,
srcPointNormals, srcPointNormals,
srcPointNormals0, srcPointNormals0,
tgtPatch, tgtPatch
tgtMap
); );
localTgtPatchPtr_.reset(localTgtPatchPtr.ptr()); localTgtPatchPtr_.reset(localTgtPatchPtr.ptr());
@ -123,15 +121,14 @@ Foam::patchToPatches::rays::distributeTgt
Foam::tmpNrc<Foam::PrimitiveOldTimePatch<Foam::faceList, Foam::pointField>> Foam::tmpNrc<Foam::PrimitiveOldTimePatch<Foam::faceList, Foam::pointField>>
Foam::patchToPatches::rays::distributeSrc Foam::patchToPatches::rays::distributeSrc
( (
const primitiveOldTimePatch& srcPatch, const primitiveOldTimePatch& srcPatch
distributionMap& srcMap
) )
{ {
// Intercept generation of the local patch. Store it. Return a const // Intercept generation of the local patch. Store it. Return a const
// reference tmp instead of a pointer. // reference tmp instead of a pointer.
tmpNrc<PrimitiveOldTimePatch<faceList, pointField>> localSrcPatchPtr = tmpNrc<PrimitiveOldTimePatch<faceList, pointField>> localSrcPatchPtr =
patchToPatch::distributeSrc(srcPatch, srcMap); patchToPatch::distributeSrc(srcPatch);
localSrcPatchPtr_.reset(localSrcPatchPtr.ptr()); localSrcPatchPtr_.reset(localSrcPatchPtr.ptr());
@ -242,6 +239,22 @@ Foam::patchToPatch::procFace Foam::patchToPatches::rays::ray
} }
Foam::tmpNrc<Foam::List<Foam::DynamicList<Foam::scalar>>>
Foam::patchToPatches::rays::srcWeights() const
{
NotImplemented;
return tmpNrc<List<DynamicList<scalar>>>(nullptr);
}
Foam::tmpNrc<Foam::List<Foam::DynamicList<Foam::scalar>>>
Foam::patchToPatches::rays::tgtWeights() const
{
NotImplemented;
return tmpNrc<List<DynamicList<scalar>>>(nullptr);
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::patchToPatches::rays::rays Foam::patchToPatches::rays::rays
@ -261,22 +274,6 @@ Foam::patchToPatches::rays::~rays()
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::tmpNrc<Foam::List<Foam::DynamicList<Foam::scalar>>>
Foam::patchToPatches::rays::srcWeights(const primitivePatch& srcPatch) const
{
NotImplemented;
return tmpNrc<List<DynamicList<scalar>>>(nullptr);
}
Foam::tmpNrc<Foam::List<Foam::DynamicList<Foam::scalar>>>
Foam::patchToPatches::rays::tgtWeights(const primitivePatch& tgtPatch) const
{
NotImplemented;
return tmpNrc<List<DynamicList<scalar>>>(nullptr);
}
Foam::patchToPatch::procFace Foam::patchToPatches::rays::srcToTgtRay Foam::patchToPatch::procFace Foam::patchToPatches::rays::srcToTgtRay
( (
const primitiveOldTimePatch& tgtPatch, const primitiveOldTimePatch& tgtPatch,

View File

@ -98,19 +98,14 @@ class rays
const primitiveOldTimePatch& srcPatch, const primitiveOldTimePatch& srcPatch,
const vectorField& srcPointNormals, const vectorField& srcPointNormals,
const vectorField& srcPointNormals0, const vectorField& srcPointNormals0,
const primitiveOldTimePatch& tgtPatch, const primitiveOldTimePatch& tgtPatch
distributionMap& tgtMap
); );
//- Distribute the source patch so that everything the target //- Distribute the source patch so that everything the target
// intersects is locally available. Happens after intersection. // intersects is locally available. Happens after intersection.
virtual virtual
tmpNrc<PrimitiveOldTimePatch<faceList, pointField>> tmpNrc<PrimitiveOldTimePatch<faceList, pointField>>
distributeSrc distributeSrc(const primitiveOldTimePatch& srcPatch);
(
const primitiveOldTimePatch& srcPatch,
distributionMap& srcMap
);
//- Finalising //- Finalising
virtual label finalise virtual label finalise
@ -137,6 +132,12 @@ class rays
point& outP point& outP
) const; ) const;
//- For each source face, the coupled target weights
virtual tmpNrc<List<DynamicList<scalar>>> srcWeights() const;
//- For each target face, the coupled source weights
virtual tmpNrc<List<DynamicList<scalar>>> tgtWeights() const;
public: public:
@ -156,18 +157,6 @@ public:
// Member Functions // Member Functions
//- For each source face, the coupled target weights
virtual tmpNrc<List<DynamicList<scalar>>> srcWeights
(
const primitivePatch& srcPatch
) const;
//- For each target face, the coupled source weights
virtual tmpNrc<List<DynamicList<scalar>>> tgtWeights
(
const primitivePatch& tgtPatch
) const;
//- Compute a ray intersection from the source side to the target //- Compute a ray intersection from the source side to the target
procFace srcToTgtRay procFace srcToTgtRay
( (

View File

@ -75,7 +75,7 @@ void thermalBaffleFvPatchScalarField::checkPatches() const
checkPatchIsMapped(nbrPp); checkPatchIsMapped(nbrPp);
const mappedPatchBase& mpp = refCast<const mappedPatchBase>(pp); const mappedPatchBase& mpp = refCast<const mappedPatchBase>(pp);
const mappedPatchBase nbrMpp = refCast<const mappedPatchBase>(nbrPp); const mappedPatchBase& nbrMpp = refCast<const mappedPatchBase>(nbrPp);
// The patches should sample a different region // The patches should sample a different region
auto checkPatchMapsDifferentRegion = [&](const mappedPatchBase& mpp) auto checkPatchMapsDifferentRegion = [&](const mappedPatchBase& mpp)