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 "wordReList.H"
#include "findCellParticle.H"
#include "mappedPatchBase.H"
#include "OBJstream.H"
#include "addToRunTimeSelectionTable.H"

View File

@ -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

View File

@ -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<Foam::mappedPatchBase::sampleMode, 4>
const Foam::NamedEnum<Foam::mappedPatchBase::sampleMode, 5>
Foam::mappedPatchBase::sampleModeNames_;
const Foam::NamedEnum<Foam::mappedPatchBase::offsetMode, 3>
@ -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<bool>("flipNormals", false)),
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())
{
@ -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<patchToPatch>(nullptr)
)
{}
@ -886,6 +939,11 @@ void Foam::mappedPatchBase::write(Ostream& os) const
os << surfDict_;
}
}
if (mode_ == PATCHTOPATCH)
{
writeEntry(os, "patchToPatchMode", patchToPatchPtr_->type());
}
}

View File

@ -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<sampleMode, 4> sampleModeNames_;
static const NamedEnum<sampleMode, 5> sampleModeNames_;
static const NamedEnum<offsetMode, 3> 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<patchToPatch> 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<pointField> 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:

View File

@ -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<mappedPatchBase>(samplePolyPatch());
}
return false;
}
inline const Foam::mappedPatchBase&
Foam::mappedPatchBase::sampleMappedPatch() const
{
return refCast<const mappedPatchBase>(samplePolyPatch());
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
inline const Foam::mappedPatchBase::sampleMode&

View File

@ -41,6 +41,25 @@ Foam::mappedPatchBase::distribute(const Field<Type>& 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<Type>& 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<Field<Type>>(nullptr);

View File

@ -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_;

View File

@ -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<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
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<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(tgtCoupleArea, sumOp<scalar>());
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::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 * * * * * * * * * * * * * * //
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::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()
:
area(Zero),
centre(point::uniform(NaN))
centre(NaN<point>())
{}
//- Default construct
@ -210,6 +210,9 @@ private:
//- The coupling geometry for for each source face
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
List<part> srcEdgeParts_;
@ -220,6 +223,9 @@ private:
//- The coupling geometry for for each target face
List<DynamicList<couple>> tgtCouples_;
//- The proportion of the target faces that are coupled
List<scalar> 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<List<DynamicList<scalar>>> srcWeights() const;
//- For each target face, the coupled source weights
virtual tmpNrc<List<DynamicList<scalar>>> tgtWeights() const;
public:
@ -393,18 +401,6 @@ public:
//- For each target face, the target and source areas for each
// source coupling
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
(
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::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 * * * * * * * * * * * * * * //
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
// 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<List<DynamicList<scalar>>> srcWeights() const;
//- For each target face, the coupled source weights
virtual tmpNrc<List<DynamicList<scalar>>> tgtWeights() const;
public:
@ -148,21 +150,6 @@ public:
//- Destructor
~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
(
const primitiveOldTimePatch& tgtPatch,
const distributionMap& tgtMap
const primitiveOldTimePatch& tgtPatch
)
{
// 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
patchToPatch::rDistributeTgt(tgtPatch, tgtMap);
patchToPatch::rDistributeTgt(tgtPatch);
// 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
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::patchToPatches::nearest::srcWeights(const primitivePatch& srcPatch) const
Foam::patchToPatches::nearest::srcWeights() const
{
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::patchToPatches::nearest::tgtWeights(const primitivePatch& tgtPatch) const
Foam::patchToPatches::nearest::tgtWeights() const
{
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
{
protected:
// Private Member Data
//- 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
// 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);
//- 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:
@ -127,21 +131,6 @@ public:
//- Destructor
~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 vectorField& srcPointNormals,
const vectorField& srcPointNormals0,
const primitiveOldTimePatch& tgtPatch,
distributionMap& tgtMap
const primitiveOldTimePatch& tgtPatch
)
{
tgtMap =
tgtMapPtr_ =
patchDistributionMap
(
tgtPatchSendFaces
@ -740,7 +739,7 @@ Foam::patchToPatch::distributeTgt
(
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::patchToPatch::distributeSrc
(
const primitiveOldTimePatch& srcPatch,
distributionMap& srcMap
const primitiveOldTimePatch& srcPatch
)
{
srcMap = patchDistributionMap(srcPatchSendFaces());
srcMapPtr_ = patchDistributionMap(srcPatchSendFaces());
if (localSrcProcFacesPtr_.empty())
{
@ -765,7 +763,7 @@ Foam::patchToPatch::distributeSrc
(
new PrimitiveOldTimePatch<faceList, pointField>
(
distributePatch(srcMap, srcPatch, localSrcProcFacesPtr_())
distributePatch(srcMapPtr_(), srcPatch, localSrcProcFacesPtr_())
)
);
}
@ -773,8 +771,7 @@ Foam::patchToPatch::distributeSrc
void Foam::patchToPatch::rDistributeTgt
(
const primitiveOldTimePatch& tgtPatch,
const distributionMap& tgtMap
const primitiveOldTimePatch& tgtPatch
)
{
// Create a map from source procFace to local source face
@ -793,7 +790,7 @@ void Foam::patchToPatch::rDistributeTgt
List<List<procFace>> tgtSrcProcFaces =
localFacesToProcFaces(tgtLocalSrcFaces_);
rDistributeListList(tgtPatch.size(), tgtMap, tgtSrcProcFaces);
rDistributeListList(tgtPatch.size(), tgtMapPtr_(), tgtSrcProcFaces);
tgtLocalSrcFaces_ =
procFacesToLocalFaces(tgtSrcProcFaces, srcProcFaceToLocal);
@ -832,10 +829,12 @@ Foam::patchToPatch::patchToPatch(const bool reverse)
:
reverse_(reverse),
singleProcess_(-labelMax),
localSrcProcFacesPtr_(nullptr),
localTgtProcFacesPtr_(nullptr),
srcLocalTgtFaces_(),
tgtLocalSrcFaces_()
tgtLocalSrcFaces_(),
srcMapPtr_(nullptr),
tgtMapPtr_(nullptr),
localSrcProcFacesPtr_(nullptr),
localTgtProcFacesPtr_(nullptr)
{}
@ -965,15 +964,13 @@ void Foam::patchToPatch::update
else
{
// Distribute the target
distributionMap tgtMap;
tmpNrc<PrimitiveOldTimePatch<faceList, pointField>> localTTgtPatchPtr =
distributeTgt
(
srcPatch,
srcPointNormals,
srcPointNormals0,
tTgtPatch,
tgtMap
tTgtPatch
);
// Massage target patch into form that can be used by the serial
@ -1008,12 +1005,11 @@ void Foam::patchToPatch::update
}
// Distribute the source
distributionMap srcMap;
tmpNrc<PrimitiveOldTimePatch<faceList, pointField>> localSrcPatchPtr =
distributeSrc(srcPatch, srcMap);
distributeSrc(srcPatch);
// Reverse distribute coupling data back to the target
rDistributeTgt(tgtPatch, tgtMap);
rDistributeTgt(tgtPatch);
}
// Finalise the intersection

View File

@ -104,6 +104,18 @@ protected:
// if spread across multiple processors
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
// source processor and face index
autoPtr<List<procFace>> localSrcProcFacesPtr_;
@ -112,12 +124,6 @@ protected:
// target processor and face index
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
@ -285,19 +291,11 @@ protected:
//- Create a distribution map from a list-list of faces to be sent
// (i.e., the result of calling one of the above methods).
distributionMap patchDistributionMap
autoPtr<distributionMap> patchDistributionMap
(
labelListList&& sendFaces
) 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
PrimitiveOldTimePatch<faceList, pointField> distributePatch
(
@ -321,8 +319,8 @@ protected:
//- Distribute the target patch so that enough is locally available
// for its intersection with the source patch can be computed.
// Happens before intersection. Bound boxes are used to determine
// what is needed where. Return the resulting local patch and the
// map from which it was calculated.
// what is needed where. Return the resulting local patch and
// internally set the target map.
virtual
tmpNrc<PrimitiveOldTimePatch<faceList, pointField>>
distributeTgt
@ -330,31 +328,22 @@ protected:
const primitiveOldTimePatch& srcPatch,
const vectorField& srcPointNormals,
const vectorField& srcPointNormals0,
const primitiveOldTimePatch& tgtPatch,
distributionMap& tgtMap
const primitiveOldTimePatch& tgtPatch
);
//- Distribute the source patch so that everything the target
// intersects is locally available. Happens after intersection.
// The intersection addressing is used to determine what is needed
// where. Return the resulting local patch and the map from which
// it was calculated.
// where. Return the resulting local patch and internally set the
// source map.
virtual
tmpNrc<PrimitiveOldTimePatch<faceList, pointField>>
distributeSrc
(
const primitiveOldTimePatch& srcPatch,
distributionMap& srcMap
);
distributeSrc(const primitiveOldTimePatch& srcPatch);
//- 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);
//- Finalising
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:
//- Runtime type information
@ -428,17 +451,32 @@ public:
//- For each target face, the coupled source procs and faces
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
virtual tmpNrc<List<DynamicList<scalar>>> tgtWeights
// Interpolation
//- ...
template<class Type>
tmp<Field<Type>> srcToTgt(const Field<Type>& srcFld) const;
//- ...
template<class Type>
tmp<Field<Type>> srcToTgt
(
const primitivePatch& tgtPatch
) const = 0;
const Field<Type>& srcFld,
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
@ -480,6 +518,12 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "patchToPatchTemplates.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -23,6 +23,7 @@ License
\*---------------------------------------------------------------------------*/
#include "autoPtr.H"
#include "patchToPatch.H"
#include "treeBoundBoxList.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
) const
@ -204,99 +205,18 @@ Foam::distributionMap Foam::patchToPatch::patchDistributionMap
// Construct and return the map
return
distributionMap
autoPtr<distributionMap>
(
new distributionMap
(
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::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 vectorField& srcPointNormals,
const vectorField& srcPointNormals0,
const primitiveOldTimePatch& tgtPatch,
distributionMap& tgtMap
const primitiveOldTimePatch& tgtPatch
)
{
// Intercept generation of the local patch. Store it. Return a const
@ -106,8 +105,7 @@ Foam::patchToPatches::rays::distributeTgt
srcPatch,
srcPointNormals,
srcPointNormals0,
tgtPatch,
tgtMap
tgtPatch
);
localTgtPatchPtr_.reset(localTgtPatchPtr.ptr());
@ -123,15 +121,14 @@ Foam::patchToPatches::rays::distributeTgt
Foam::tmpNrc<Foam::PrimitiveOldTimePatch<Foam::faceList, Foam::pointField>>
Foam::patchToPatches::rays::distributeSrc
(
const primitiveOldTimePatch& srcPatch,
distributionMap& srcMap
const primitiveOldTimePatch& srcPatch
)
{
// Intercept generation of the local patch. Store it. Return a const
// reference tmp instead of a pointer.
tmpNrc<PrimitiveOldTimePatch<faceList, pointField>> localSrcPatchPtr =
patchToPatch::distributeSrc(srcPatch, srcMap);
patchToPatch::distributeSrc(srcPatch);
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 * * * * * * * * * * * * * * //
Foam::patchToPatches::rays::rays
@ -261,22 +274,6 @@ Foam::patchToPatches::rays::~rays()
// * * * * * * * * * * * * * * * 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
(
const primitiveOldTimePatch& tgtPatch,

View File

@ -98,19 +98,14 @@ class rays
const primitiveOldTimePatch& srcPatch,
const vectorField& srcPointNormals,
const vectorField& srcPointNormals0,
const primitiveOldTimePatch& tgtPatch,
distributionMap& tgtMap
const primitiveOldTimePatch& tgtPatch
);
//- Distribute the source patch so that everything the target
// intersects is locally available. Happens after intersection.
virtual
tmpNrc<PrimitiveOldTimePatch<faceList, pointField>>
distributeSrc
(
const primitiveOldTimePatch& srcPatch,
distributionMap& srcMap
);
distributeSrc(const primitiveOldTimePatch& srcPatch);
//- Finalising
virtual label finalise
@ -137,6 +132,12 @@ class rays
point& outP
) 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:
@ -156,18 +157,6 @@ public:
// 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
procFace srcToTgtRay
(

View File

@ -75,7 +75,7 @@ void thermalBaffleFvPatchScalarField::checkPatches() const
checkPatchIsMapped(nbrPp);
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
auto checkPatchMapsDifferentRegion = [&](const mappedPatchBase& mpp)