ENH: AMI code refactoring

This commit is contained in:
Andrew Heather
2020-05-18 07:41:46 +01:00
committed by Andrew Heather
parent 2a955ad949
commit c6e18e7593
36 changed files with 2440 additions and 2827 deletions

View File

@ -226,10 +226,9 @@ void Foam::cyclicACMIFvPatchField<Type>::updateInterfaceMatrix
{ {
const cyclicACMIPolyPatch& cpp = cyclicACMIPatch_.cyclicACMIPatch(); const cyclicACMIPolyPatch& cpp = cyclicACMIPatch_.cyclicACMIPatch();
// note: only applying coupled contribution // Note: only applying coupled contribution
const labelUList& nbrFaceCellsCoupled = const labelUList& nbrFaceCellsCoupled = cpp.neighbPatch().faceCells();
cpp.neighbPatch().faceCells();
solveScalarField pnf(psiInternal, nbrFaceCellsCoupled); solveScalarField pnf(psiInternal, nbrFaceCellsCoupled);
@ -254,7 +253,7 @@ void Foam::cyclicACMIFvPatchField<Type>::updateInterfaceMatrix
{ {
const cyclicACMIPolyPatch& cpp = cyclicACMIPatch_.cyclicACMIPatch(); const cyclicACMIPolyPatch& cpp = cyclicACMIPatch_.cyclicACMIPatch();
// note: only applying coupled contribution // Note: only applying coupled contribution
const labelUList& nbrFaceCellsCoupled = cpp.neighbPatch().faceCells(); const labelUList& nbrFaceCellsCoupled = cpp.neighbPatch().faceCells();
@ -277,7 +276,7 @@ void Foam::cyclicACMIFvPatchField<Type>::manipulateMatrix
{ {
const scalarField& mask = cyclicACMIPatch_.cyclicACMIPatch().mask(); const scalarField& mask = cyclicACMIPatch_.cyclicACMIPatch().mask();
// nothing to be done by the AMI, but re-direct to non-overlap patch // Nothing to be done by the AMI, but re-direct to non-overlap patch
// with non-overlap patch weights // with non-overlap patch weights
const fvPatchField<Type>& npf = nonOverlapPatchField(); const fvPatchField<Type>& npf = nonOverlapPatchField();

View File

@ -46,6 +46,7 @@ namespace Foam
void Foam::cyclicACMIFvPatch::resetPatchAreas(const fvPatch& fvp) const void Foam::cyclicACMIFvPatch::resetPatchAreas(const fvPatch& fvp) const
{ {
const_cast<vectorField&>(fvp.Sf()) = fvp.patch().faceAreas(); const_cast<vectorField&>(fvp.Sf()) = fvp.patch().faceAreas();
const_cast<vectorField&>(fvp.Cf()) = fvp.patch().faceCentres();
const_cast<scalarField&>(fvp.magSf()) = mag(fvp.patch().faceAreas()); const_cast<scalarField&>(fvp.magSf()) = mag(fvp.patch().faceAreas());
DebugPout DebugPout
@ -117,7 +118,7 @@ Foam::tmp<Foam::vectorField> Foam::cyclicACMIFvPatch::delta() const
vectorField nbrPatchD(interpolate(nbrPatch.coupledFvPatch::delta())); vectorField nbrPatchD(interpolate(nbrPatch.coupledFvPatch::delta()));
tmp<vectorField> tpdv(new vectorField(patchD.size())); auto tpdv = tmp<vectorField>::New(patchD.size());
vectorField& pdv = tpdv.ref(); vectorField& pdv = tpdv.ref();
// do the transformation if necessary // do the transformation if necessary
@ -204,6 +205,9 @@ void Foam::cyclicACMIFvPatch::movePoints()
scalarField& phiNonOverlapp = scalarField& phiNonOverlapp =
meshPhiBf[nonOverlapPatch.patch().index()]; meshPhiBf[nonOverlapPatch.patch().index()];
const auto& localFaces = cyclicACMIPolyPatch_.localFaces();
const auto& localPoints = cyclicACMIPolyPatch_.localPoints();
forAll(phip, facei) forAll(phip, facei)
{ {
if (newSrcAddr[facei].empty()) if (newSrcAddr[facei].empty())
@ -214,12 +218,12 @@ void Foam::cyclicACMIFvPatch::movePoints()
else else
{ {
// Scale the mesh flux according to the area fraction // Scale the mesh flux according to the area fraction
const face& fAMI = cyclicACMIPolyPatch_.localFaces()[facei]; const face& fAMI = localFaces[facei];
// Note: using raw point locations to calculate the geometric // Note: using raw point locations to calculate the geometric
// area - faces areas are currently scaled (decoupled from // area - faces areas are currently scaled (decoupled from
// mesh points) // mesh points)
const scalar geomArea = fAMI.mag(cyclicACMIPolyPatch_.localPoints()); const scalar geomArea = fAMI.mag(localPoints);
phip[facei] *= magSf()[facei]/geomArea; phip[facei] *= magSf()[facei]/geomArea;
} }
} }
@ -234,6 +238,9 @@ void Foam::cyclicACMIFvPatch::movePoints()
scalarField& nbrPhiNonOverlapp = scalarField& nbrPhiNonOverlapp =
meshPhiBf[nbrNonOverlapPatch.patch().index()]; meshPhiBf[nbrNonOverlapPatch.patch().index()];
const auto& nbrLocalFaces = nbrACMI.patch().localFaces();
const auto& nbrLocalPoints = nbrACMI.patch().localPoints();
forAll(nbrPhip, facei) forAll(nbrPhip, facei)
{ {
if (newTgtAddr[facei].empty()) if (newTgtAddr[facei].empty())
@ -242,12 +249,12 @@ void Foam::cyclicACMIFvPatch::movePoints()
} }
else else
{ {
const face& fAMI = nbrACMI.patch().localFaces()[facei]; const face& fAMI = nbrLocalFaces[facei];
// Note: using raw point locations to calculate the geometric // Note: using raw point locations to calculate the geometric
// area - faces areas are currently scaled (decoupled from // area - faces areas are currently scaled (decoupled from
// mesh points) // mesh points)
const scalar geomArea = fAMI.mag(nbrACMI.patch().localPoints()); const scalar geomArea = fAMI.mag(nbrLocalPoints);
nbrPhip[facei] *= nbrACMI.magSf()[facei]/geomArea; nbrPhip[facei] *= nbrACMI.magSf()[facei]/geomArea;
} }
} }

View File

@ -6,6 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2019-2020 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -123,7 +124,7 @@ Foam::tmp<Foam::vectorField> Foam::cyclicAMIFvPatch::delta() const
const vectorField& nbrPatchD = tnbrPatchD(); const vectorField& nbrPatchD = tnbrPatchD();
tmp<vectorField> tpdv(new vectorField(patchD.size())); auto tpdv = tmp<vectorField>::New(patchD.size());
vectorField& pdv = tpdv.ref(); vectorField& pdv = tpdv.ref();
// do the transformation if necessary // do the transformation if necessary

View File

@ -159,8 +159,8 @@ public:
} }
//- Return true if this patch is coupled. This is equivalent //- Return true if this patch is coupled. This is equivalent
// to the coupledPolyPatch::coupled() if parallel running or //- to the coupledPolyPatch::coupled() if parallel running or
// both sides present, false otherwise //- both sides present, false otherwise
virtual bool coupled() const; virtual bool coupled() const;
//- Return delta (P to N) vectors across coupled patch //- Return delta (P to N) vectors across coupled patch
@ -190,7 +190,7 @@ public:
// Interface transfer functions // Interface transfer functions
//- Return the values of the given internal data adjacent to //- Return the values of the given internal data adjacent to
// the interface as a field //- the interface as a field
virtual tmp<labelField> interfaceInternalField virtual tmp<labelField> interfaceInternalField
( (
const labelUList& internalData const labelUList& internalData

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2016-2018 OpenCFD Ltd. Copyright (C) 2016-2020 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -62,75 +62,52 @@ SourceFiles
#include "ops.H" #include "ops.H"
#include "Enum.H" #include "Enum.H"
#include "pointList.H" #include "pointList.H"
#include "indexedOctree.H"
#include "treeDataPrimitivePatch.H"
#include "runTimeSelectionTables.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam namespace Foam
{ {
/*---------------------------------------------------------------------------*\
Class AMIInterpolationName Declaration
\*---------------------------------------------------------------------------*/
TemplateName(AMIInterpolation);
/*---------------------------------------------------------------------------*\ /*---------------------------------------------------------------------------*\
Class AMIInterpolation Declaration Class AMIInterpolation Declaration
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
template<class SourcePatch, class TargetPatch>
class AMIInterpolation class AMIInterpolation
:
public AMIInterpolationName
{ {
public: public:
// Public data types // Public data types
//- Enumeration specifying interpolation method
enum interpolationMethod
{
imNearestFace,
imFaceAreaWeight,
imPartialFaceAreaWeight
};
static const Enum<interpolationMethod> interpolationMethodNames_;
static bool cacheIntersections_; static bool cacheIntersections_;
//- Calculate the patch face magnitudes for the given tri-mode
template<class Patch>
static tmp<scalarField> patchMagSf
(
const Patch& patch,
const faceAreaIntersect::triangulationMode triMode
);
protected:
private: //- Local typedef to octree tree-type
typedef treeDataPrimitivePatch<primitivePatch> treeType;
// Private data // Protected data
//- Interpolation method //- Flag to indicate that the two patches must be matched/an overlap
const word methodName_; //- exists between them
bool requireMatch_;
//- Flag to indicate that the two patches are co-directional and //- Flag to indicate that the two patches are co-directional and
//- that the orientation of the target patch should be reversed //- that the orientation of the target patch should be reversed
const bool reverseTarget_; const bool reverseTarget_;
//- Flag to indicate that the two patches must be matched/an overlap //- Threshold weight below which interpolation is deactivated
//- exists between them scalar lowWeightCorrection_;
const bool requireMatch_;
//- Index of processor that holds all of both sides. -1 in all other //- Index of processor that holds all of both sides. -1 in all other
//- cases //- cases
label singlePatchProc_; label singlePatchProc_;
//- Threshold weight below which interpolation is deactivated
scalar lowWeightCorrection_;
// Source patch // Source patch
@ -149,6 +126,16 @@ private:
//- Centroid of target faces per source face //- Centroid of target faces per source face
pointListList srcCentroids_; pointListList srcCentroids_;
//- Source patch points if input points are manipulated, e.g.
//- projected
pointField srcPatchPts_;
//- Source patch using manipulated input points
tmpNrc<primitivePatch> tsrcPatch0_;
//- Source map pointer - parallel running only
autoPtr<mapDistribute> srcMapPtr_;
// Target patch // Target patch
@ -167,21 +154,21 @@ private:
//- Centroid of source faces per target face //- Centroid of source faces per target face
pointListList tgtCentroids_; pointListList tgtCentroids_;
//- Target patch points if input points are manipulated, e.g.
//- projected
pointField tgtPatchPts_;
//- Face triangulation mode //- Target patch using manipulated input points
const faceAreaIntersect::triangulationMode triMode_; tmpNrc<primitivePatch> ttgtPatch0_;
//- Source map pointer - parallel running only //- Target map pointer - parallel running only
autoPtr<mapDistribute> srcMapPtr_; autoPtr<mapDistribute> tgtMapPtr_;
//- Target map pointer - parallel running only //- Up-to-date flag
autoPtr<mapDistribute> tgtMapPtr_; bool upToDate_;
// Private Member Functions // Protected Member Functions
//- No copy construct
AMIInterpolation(const AMIInterpolation&) = delete;
//- No copy assignment //- No copy assignment
void operator=(const AMIInterpolation&) = delete; void operator=(const AMIInterpolation&) = delete;
@ -189,6 +176,19 @@ private:
// Initialisation // Initialisation
//- Reset the octree for the patch face search
autoPtr<indexedOctree<treeType>> createTree
(
const primitivePatch& patch
) const;
//- Calculate if patches are on multiple processors
label calcDistribution
(
const primitivePatch& srcPatch,
const primitivePatch& tgtPatch
) const;
//- Project points to surface //- Project points to surface
void projectPointsToSurface void projectPointsToSurface
( (
@ -197,6 +197,15 @@ private:
) const; ) const;
// Access
//- Return the orginal src patch with optionally updated points
inline const primitivePatch& srcPatch0() const;
//- Return the orginal tgt patch with optionally updated points
inline const primitivePatch& tgtPatch0() const;
// Evaluation // Evaluation
//- Normalise the (area) weights - suppresses numerical error in //- Normalise the (area) weights - suppresses numerical error in
@ -236,96 +245,127 @@ private:
autoPtr<mapDistribute>& tgtMap autoPtr<mapDistribute>& tgtMap
); );
void constructFromSurface
(
const SourcePatch& srcPatch,
const TargetPatch& tgtPatch,
const autoPtr<searchableSurface>& surfPtr
);
public: public:
//- Runtime type information
TypeName("AMIInterpolation");
// Selection tables
//- Selection table for dictionary construction
declareRunTimeSelectionTable
(
autoPtr,
AMIInterpolation,
dict,
(
const dictionary& dict,
const bool reverseTarget
),
(
dict,
reverseTarget
)
);
//- Selection table for component-wise construction
declareRunTimeSelectionTable
(
autoPtr,
AMIInterpolation,
component,
(
const bool requireMatch,
const bool reverseTarget,
const scalar lowWeightCorrection
),
(
requireMatch,
reverseTarget,
lowWeightCorrection
)
);
//- Selector for dictionary
static autoPtr<AMIInterpolation> New
(
const word& modelName,
const dictionary& dict,
const bool reverseTarget = false
);
//- Selector for components
static autoPtr<AMIInterpolation> New
(
const word& modelName,
const bool requireMatch = true,
const bool reverseTarget = false,
const scalar lowWeightCorrection = -1
);
// Constructors // Constructors
//- Construct from components //- Construct from dictionary
AMIInterpolation AMIInterpolation
( (
const SourcePatch& srcPatch, const dictionary& dict,
const TargetPatch& tgtPatch,
const faceAreaIntersect::triangulationMode& triMode,
const bool requireMatch = true,
const interpolationMethod& method = imFaceAreaWeight,
const scalar lowWeightCorrection = -1,
const bool reverseTarget = false const bool reverseTarget = false
); );
//- Construct from components //- Construct from components
AMIInterpolation AMIInterpolation
( (
const SourcePatch& srcPatch,
const TargetPatch& tgtPatch,
const faceAreaIntersect::triangulationMode& triMode,
const bool requireMatch = true, const bool requireMatch = true,
const word& methodName = const bool reverseTarget = false,
interpolationMethodNames_[imFaceAreaWeight], const scalar lowWeightCorrection = -1
const scalar lowWeightCorrection = -1,
const bool reverseTarget = false
);
//- Construct from components, with projection surface
AMIInterpolation
(
const SourcePatch& srcPatch,
const TargetPatch& tgtPatch,
const autoPtr<searchableSurface>& surf,
const faceAreaIntersect::triangulationMode& triMode,
const bool requireMatch = true,
const interpolationMethod& method = imFaceAreaWeight,
const scalar lowWeightCorrection = -1,
const bool reverseTarget = false
);
//- Construct from components, with projection surface
AMIInterpolation
(
const SourcePatch& srcPatch,
const TargetPatch& tgtPatch,
const autoPtr<searchableSurface>& surf,
const faceAreaIntersect::triangulationMode& triMode,
const bool requireMatch = true,
const word& methodName =
interpolationMethodNames_[imFaceAreaWeight],
const scalar lowWeightCorrection = -1,
const bool reverseTarget = false
); );
//- Construct from agglomeration of AMIInterpolation. Agglomeration //- Construct from agglomeration of AMIInterpolation. Agglomeration
// passed in as new coarse size and addressing from fine from coarse //- passed in as new coarse size and addressing from fine from coarse
AMIInterpolation AMIInterpolation
( (
const AMIInterpolation<SourcePatch, TargetPatch>& fineAMI, const AMIInterpolation& fineAMI,
const labelList& sourceRestrictAddressing, const labelList& sourceRestrictAddressing,
const labelList& neighbourRestrictAddressing const labelList& neighbourRestrictAddressing
); );
//- Construct as copy
AMIInterpolation(const AMIInterpolation& ami);
//- Construct and return a clone
virtual autoPtr<AMIInterpolation> clone() const
{
return autoPtr<AMIInterpolation>::New(*this);
}
//- Destructor //- Destructor
~AMIInterpolation() = default; virtual ~AMIInterpolation() = default;
// Typedef to SourcePatch type this AMIInterpolation is instantiated on
typedef SourcePatch sourcePatchType;
// Typedef to TargetPatch type this AMIInterpolation is instantiated on
typedef TargetPatch targetPatchType;
// Member Functions // Member Functions
// Access // Access
//- Set to -1, or the processor holding all faces (both sides) of //- Access to the up-to-date flag
//- the AMI inline bool upToDate() const;
inline label singlePatchProc() const;
//- Access to the up-to-date flag
inline bool& upToDate();
//- Access to the distributed flag
inline bool distributed() const;
//- Access to the requireMatch flag
inline bool requireMatch() const;
//- Access to the requireMatch flag
inline bool setRequireMatch(const bool flag);
//- Access to the reverseTarget flag
inline bool reverseTarget() const;
//- Threshold weight below which interpolation is deactivated //- Threshold weight below which interpolation is deactivated
inline scalar lowWeightCorrection() const; inline scalar lowWeightCorrection() const;
@ -333,6 +373,10 @@ public:
//- Return true if employing a 'lowWeightCorrection' //- Return true if employing a 'lowWeightCorrection'
inline bool applyLowWeightCorrection() const; inline bool applyLowWeightCorrection() const;
//- Set to -1, or the processor holding all faces (both sides) of
//- the AMI
inline label singlePatchProc() const;
// Source patch // Source patch
@ -410,14 +454,16 @@ public:
// Manipulation // Manipulation
//- Update addressing and weights //- Update addressing, weights and (optional) centroids
void update virtual bool calculate
( (
const SourcePatch& srcPatch, const primitivePatch& srcPatch,
const TargetPatch& tgtPatch const primitivePatch& tgtPatch,
const autoPtr<searchableSurface>& surfPtr = nullptr
); );
void update //- Set the maps, addresses and weights from an external source
void reset
( (
autoPtr<mapDistribute>&& srcToTgtMap, autoPtr<mapDistribute>&& srcToTgtMap,
autoPtr<mapDistribute>&& tgtToSrcMap, autoPtr<mapDistribute>&& tgtToSrcMap,
@ -427,17 +473,11 @@ public:
scalarListList&& tgtWeights scalarListList&& tgtWeights
); );
void setAreas(const scalarList& srcMagSf, const scalarList& tgtMagSf)
{
srcMagSf_ = srcMagSf;
tgtMagSf_ = tgtMagSf;
}
//- Append additional addressing and weights //- Append additional addressing and weights
void append void append
( (
const SourcePatch& srcPatch, const primitivePatch& srcPatch,
const TargetPatch& tgtPatch const primitivePatch& tgtPatch
); );
//- Normalise the weights //- Normalise the weights
@ -545,8 +585,8 @@ public:
//- Return source patch face index of point on target patch face //- Return source patch face index of point on target patch face
label srcPointFace label srcPointFace
( (
const SourcePatch& srcPatch, const primitivePatch& srcPatch,
const TargetPatch& tgtPatch, const primitivePatch& tgtPatch,
const vector& n, const vector& n,
const label tgtFacei, const label tgtFacei,
point& tgtPoint point& tgtPoint
@ -556,8 +596,8 @@ public:
//- Return target patch face index of point on source patch face //- Return target patch face index of point on source patch face
label tgtPointFace label tgtPointFace
( (
const SourcePatch& srcPatch, const primitivePatch& srcPatch,
const TargetPatch& tgtPatch, const primitivePatch& tgtPatch,
const vector& n, const vector& n,
const label srcFacei, const label srcFacei,
point& srcPoint point& srcPoint
@ -574,10 +614,16 @@ public:
//- Write face connectivity as OBJ file //- Write face connectivity as OBJ file
void writeFaceConnectivity void writeFaceConnectivity
( (
const SourcePatch& srcPatch, const primitivePatch& srcPatch,
const TargetPatch& tgtPatch, const primitivePatch& tgtPatch,
const labelListList& srcAddress const labelListList& srcAddress
) const; ) const;
// I-O
//- Write
virtual void write(Ostream& os) const;
}; };
@ -592,7 +638,7 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository #ifdef NoRepository
#include "AMIInterpolation.C" #include "AMIInterpolationTemplates.C"
#endif #endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2016 OpenCFD Ltd. Copyright (C) 2016-2020 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -26,186 +26,203 @@ License
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
template<class SourcePatch, class TargetPatch> inline const Foam::primitivePatch& Foam::AMIInterpolation::srcPatch0() const
inline Foam::label
Foam::AMIInterpolation<SourcePatch, TargetPatch>::singlePatchProc() const
{ {
return singlePatchProc_; if (!tsrcPatch0_.valid())
{
FatalErrorInFunction
<< "tsrcPatch0Ptr_ not set"
<< abort(FatalError);
}
return tsrcPatch0_();
} }
template<class SourcePatch, class TargetPatch> inline const Foam::primitivePatch& Foam::AMIInterpolation::tgtPatch0() const
inline Foam::scalar {
Foam::AMIInterpolation<SourcePatch, TargetPatch>::lowWeightCorrection() const
if (!ttgtPatch0_.valid())
{
FatalErrorInFunction
<< "ttgtPatch0Ptr_ not set"
<< abort(FatalError);
}
return ttgtPatch0_();
}
inline bool Foam::AMIInterpolation::upToDate() const
{
return upToDate_;
}
inline bool& Foam::AMIInterpolation::upToDate()
{
return upToDate_;
}
inline bool Foam::AMIInterpolation::distributed() const
{
return singlePatchProc_ == -1;
}
inline bool Foam::AMIInterpolation::requireMatch() const
{
return requireMatch_ && lowWeightCorrection_ < 0;
}
inline bool Foam::AMIInterpolation::setRequireMatch(const bool flag)
{
requireMatch_ = flag;
return requireMatch_;
}
inline bool Foam::AMIInterpolation::reverseTarget() const
{
return reverseTarget_;
}
inline Foam::scalar Foam::AMIInterpolation::lowWeightCorrection() const
{ {
return lowWeightCorrection_; return lowWeightCorrection_;
} }
template<class SourcePatch, class TargetPatch> inline bool Foam::AMIInterpolation::applyLowWeightCorrection() const
inline bool
Foam::AMIInterpolation<SourcePatch, TargetPatch>::
applyLowWeightCorrection() const
{ {
return lowWeightCorrection_ > 0; return lowWeightCorrection_ > 0;
} }
template<class SourcePatch, class TargetPatch> inline Foam::label Foam::AMIInterpolation::singlePatchProc() const
inline const Foam::List<Foam::scalar>& {
Foam::AMIInterpolation<SourcePatch, TargetPatch>::srcMagSf() const return singlePatchProc_;
}
inline const Foam::List<Foam::scalar>& Foam::AMIInterpolation::srcMagSf() const
{ {
return srcMagSf_; return srcMagSf_;
} }
template<class SourcePatch, class TargetPatch> inline Foam::List<Foam::scalar>& Foam::AMIInterpolation::srcMagSf()
inline Foam::List<Foam::scalar>&
Foam::AMIInterpolation<SourcePatch, TargetPatch>::srcMagSf()
{ {
return srcMagSf_; return srcMagSf_;
} }
template<class SourcePatch, class TargetPatch> inline const Foam::labelListList& Foam::AMIInterpolation::srcAddress() const
inline const Foam::labelListList&
Foam::AMIInterpolation<SourcePatch, TargetPatch>::srcAddress() const
{ {
return srcAddress_; return srcAddress_;
} }
template<class SourcePatch, class TargetPatch> inline Foam::labelListList& Foam::AMIInterpolation::srcAddress()
inline Foam::labelListList&
Foam::AMIInterpolation<SourcePatch, TargetPatch>::srcAddress()
{ {
return srcAddress_; return srcAddress_;
} }
template<class SourcePatch, class TargetPatch> inline const Foam::scalarListList& Foam::AMIInterpolation::srcWeights() const
inline const Foam::scalarListList&
Foam::AMIInterpolation<SourcePatch, TargetPatch>::srcWeights() const
{ {
return srcWeights_; return srcWeights_;
} }
template<class SourcePatch, class TargetPatch> inline Foam::scalarListList& Foam::AMIInterpolation::srcWeights()
inline Foam::scalarListList&
Foam::AMIInterpolation<SourcePatch, TargetPatch>::srcWeights()
{ {
return srcWeights_; return srcWeights_;
} }
template<class SourcePatch, class TargetPatch> inline const Foam::scalarField& Foam::AMIInterpolation::srcWeightsSum() const
inline const Foam::scalarField&
Foam::AMIInterpolation<SourcePatch, TargetPatch>::srcWeightsSum() const
{ {
return srcWeightsSum_; return srcWeightsSum_;
} }
template<class SourcePatch, class TargetPatch> inline Foam::scalarField& Foam::AMIInterpolation::srcWeightsSum()
inline Foam::scalarField&
Foam::AMIInterpolation<SourcePatch, TargetPatch>::srcWeightsSum()
{ {
return srcWeightsSum_; return srcWeightsSum_;
} }
template<class SourcePatch, class TargetPatch> inline const Foam::pointListList& Foam::AMIInterpolation::srcCentroids() const
inline const Foam::pointListList&
Foam::AMIInterpolation<SourcePatch, TargetPatch>::srcCentroids() const
{ {
return srcCentroids_; return srcCentroids_;
} }
template<class SourcePatch, class TargetPatch> inline Foam::pointListList& Foam::AMIInterpolation::srcCentroids()
inline Foam::pointListList&
Foam::AMIInterpolation<SourcePatch, TargetPatch>::srcCentroids()
{ {
return srcCentroids_; return srcCentroids_;
} }
template<class SourcePatch, class TargetPatch> inline const Foam::mapDistribute& Foam::AMIInterpolation::srcMap() const
inline const Foam::mapDistribute&
Foam::AMIInterpolation<SourcePatch, TargetPatch>::srcMap() const
{ {
return *srcMapPtr_; return *srcMapPtr_;
} }
template<class SourcePatch, class TargetPatch> inline const Foam::List<Foam::scalar>& Foam::AMIInterpolation::tgtMagSf() const
inline const Foam::List<Foam::scalar>&
Foam::AMIInterpolation<SourcePatch, TargetPatch>::tgtMagSf() const
{ {
return tgtMagSf_; return tgtMagSf_;
} }
template<class SourcePatch, class TargetPatch> inline Foam::List<Foam::scalar>& Foam::AMIInterpolation::tgtMagSf()
inline Foam::List<Foam::scalar>&
Foam::AMIInterpolation<SourcePatch, TargetPatch>::tgtMagSf()
{ {
return tgtMagSf_; return tgtMagSf_;
} }
template<class SourcePatch, class TargetPatch> inline const Foam::labelListList& Foam::AMIInterpolation::tgtAddress() const
inline const Foam::labelListList&
Foam::AMIInterpolation<SourcePatch, TargetPatch>::tgtAddress() const
{ {
return tgtAddress_; return tgtAddress_;
} }
template<class SourcePatch, class TargetPatch> inline Foam::labelListList& Foam::AMIInterpolation::tgtAddress()
inline Foam::labelListList&
Foam::AMIInterpolation<SourcePatch, TargetPatch>::tgtAddress()
{ {
return tgtAddress_; return tgtAddress_;
} }
template<class SourcePatch, class TargetPatch> inline const Foam::scalarListList& Foam::AMIInterpolation::tgtWeights() const
inline const Foam::scalarListList&
Foam::AMIInterpolation<SourcePatch, TargetPatch>::tgtWeights() const
{ {
return tgtWeights_; return tgtWeights_;
} }
template<class SourcePatch, class TargetPatch> inline Foam::scalarListList& Foam::AMIInterpolation::tgtWeights()
inline Foam::scalarListList&
Foam::AMIInterpolation<SourcePatch, TargetPatch>::tgtWeights()
{ {
return tgtWeights_; return tgtWeights_;
} }
template<class SourcePatch, class TargetPatch> inline const Foam::scalarField& Foam::AMIInterpolation::tgtWeightsSum() const
inline const Foam::scalarField&
Foam::AMIInterpolation<SourcePatch, TargetPatch>::tgtWeightsSum() const
{ {
return tgtWeightsSum_; return tgtWeightsSum_;
} }
template<class SourcePatch, class TargetPatch> inline Foam::scalarField& Foam::AMIInterpolation::tgtWeightsSum()
inline Foam::scalarField&
Foam::AMIInterpolation<SourcePatch, TargetPatch>::tgtWeightsSum()
{ {
return tgtWeightsSum_; return tgtWeightsSum_;
} }
template<class SourcePatch, class TargetPatch> inline const Foam::mapDistribute& Foam::AMIInterpolation::tgtMap() const
inline const Foam::mapDistribute&
Foam::AMIInterpolation<SourcePatch, TargetPatch>::tgtMap() const
{ {
return *tgtMapPtr_; return *tgtMapPtr_;
} }

View File

@ -1,38 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2012 OpenFOAM Foundation
-------------------------------------------------------------------------------
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 "AMIInterpolation.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(AMIInterpolationName, 0);
}
// ************************************************************************* //

View File

@ -5,8 +5,7 @@
\\ / A nd | www.openfoam.com \\ / A nd | www.openfoam.com
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2013-2016 OpenFOAM Foundation Copyright (C) 2020 OpenCFD Ltd.
Copyright (C) 2019 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -26,46 +25,66 @@ License
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#include "AMIInterpolation.H"
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class SourcePatch, class TargetPatch> Foam::autoPtr<Foam::AMIInterpolation> Foam::AMIInterpolation::New
Foam::autoPtr<Foam::AMIMethod<SourcePatch, TargetPatch>>
Foam::AMIMethod<SourcePatch, TargetPatch>::New
( (
const word& methodName, const word& modelName,
const SourcePatch& srcPatch, const dictionary& dict,
const TargetPatch& tgtPatch, const bool reverseTarget
const faceAreaIntersect::triangulationMode& triMode,
const bool reverseTarget,
const bool requireMatch
) )
{ {
DebugInfo << "Selecting AMIMethod " << methodName << endl; DebugInfo << "Selecting model " << modelName << endl;
auto cstrIter = componentsConstructorTablePtr_->cfind(methodName); auto cstrIter = dictConstructorTablePtr_->cfind(modelName);
if (!cstrIter.found()) if (!cstrIter.found())
{ {
FatalErrorInLookup FatalErrorInLookup
( (
"AMIMethod", typeName,
methodName, modelName,
*componentsConstructorTablePtr_ *dictConstructorTablePtr_
) << exit(FatalError); ) << exit(FatalError);
} }
return autoPtr<AMIMethod<SourcePatch, TargetPatch>> return autoPtr<AMIInterpolation>(cstrIter()(dict, reverseTarget));
}
Foam::autoPtr<Foam::AMIInterpolation> Foam::AMIInterpolation::New
(
const word& modelName,
const bool requireMatch,
const bool reverseTarget,
const scalar lowWeightCorrection
)
{
DebugInfo << "Selecting model " << modelName << endl;
auto cstrIter = componentConstructorTablePtr_->cfind(modelName);
if (!cstrIter.found())
{
FatalErrorInLookup
(
typeName,
modelName,
*componentConstructorTablePtr_
) << exit(FatalError);
}
return autoPtr<AMIInterpolation>
( (
cstrIter() cstrIter()
( (
srcPatch, requireMatch,
tgtPatch,
triMode,
reverseTarget, reverseTarget,
requireMatch lowWeightCorrection
) )
); );
} }
// ************************************************************************* // // ************************************************************************* //

View File

@ -0,0 +1,318 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2015-2018 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "profiling.H"
#include "mapDistribute.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
template<class Type, class CombineOp>
void Foam::AMIInterpolation::interpolateToTarget
(
const UList<Type>& fld,
const CombineOp& cop,
List<Type>& result,
const UList<Type>& defaultValues
) const
{
addProfiling(ami, "AMIInterpolation::interpolateToTarget");
if (fld.size() != srcAddress_.size())
{
FatalErrorInFunction
<< "Supplied field size is not equal to source patch size" << nl
<< " source patch = " << srcAddress_.size() << nl
<< " target patch = " << tgtAddress_.size() << nl
<< " supplied field = " << fld.size()
<< abort(FatalError);
}
if (lowWeightCorrection_ > 0)
{
if (defaultValues.size() != tgtAddress_.size())
{
FatalErrorInFunction
<< "Employing default values when sum of weights falls below "
<< lowWeightCorrection_
<< " but supplied default field size is not equal to target "
<< "patch size" << nl
<< " default values = " << defaultValues.size() << nl
<< " target patch = " << tgtAddress_.size() << nl
<< abort(FatalError);
}
}
result.setSize(tgtAddress_.size());
if (distributed())
{
const mapDistribute& map = srcMapPtr_();
List<Type> work(fld);
map.distribute(work);
forAll(result, facei)
{
if (tgtWeightsSum_[facei] < lowWeightCorrection_)
{
result[facei] = defaultValues[facei];
}
else
{
const labelList& faces = tgtAddress_[facei];
const scalarList& weights = tgtWeights_[facei];
forAll(faces, i)
{
cop(result[facei], facei, work[faces[i]], weights[i]);
}
}
}
}
else
{
forAll(result, facei)
{
if (tgtWeightsSum_[facei] < lowWeightCorrection_)
{
result[facei] = defaultValues[facei];
}
else
{
const labelList& faces = tgtAddress_[facei];
const scalarList& weights = tgtWeights_[facei];
forAll(faces, i)
{
cop(result[facei], facei, fld[faces[i]], weights[i]);
}
}
}
}
}
template<class Type, class CombineOp>
void Foam::AMIInterpolation::interpolateToSource
(
const UList<Type>& fld,
const CombineOp& cop,
List<Type>& result,
const UList<Type>& defaultValues
) const
{
addProfiling(ami, "AMIInterpolation::interpolateToSource");
if (fld.size() != tgtAddress_.size())
{
FatalErrorInFunction
<< "Supplied field size is not equal to target patch size" << nl
<< " source patch = " << srcAddress_.size() << nl
<< " target patch = " << tgtAddress_.size() << nl
<< " supplied field = " << fld.size()
<< abort(FatalError);
}
if (lowWeightCorrection_ > 0)
{
if (defaultValues.size() != srcAddress_.size())
{
FatalErrorInFunction
<< "Employing default values when sum of weights falls below "
<< lowWeightCorrection_
<< " but supplied default field size is not equal to source "
<< "patch size" << nl
<< " default values = " << defaultValues.size() << nl
<< " source patch = " << srcAddress_.size() << nl
<< abort(FatalError);
}
}
result.setSize(srcAddress_.size());
if (distributed())
{
const mapDistribute& map = tgtMapPtr_();
List<Type> work(fld);
map.distribute(work);
forAll(result, facei)
{
if (srcWeightsSum_[facei] < lowWeightCorrection_)
{
result[facei] = defaultValues[facei];
}
else
{
const labelList& faces = srcAddress_[facei];
const scalarList& weights = srcWeights_[facei];
forAll(faces, i)
{
cop(result[facei], facei, work[faces[i]], weights[i]);
}
}
}
}
else
{
forAll(result, facei)
{
if (srcWeightsSum_[facei] < lowWeightCorrection_)
{
result[facei] = defaultValues[facei];
}
else
{
const labelList& faces = srcAddress_[facei];
const scalarList& weights = srcWeights_[facei];
forAll(faces, i)
{
cop(result[facei], facei, fld[faces[i]], weights[i]);
}
}
}
}
}
template<class Type, class CombineOp>
Foam::tmp<Foam::Field<Type>> Foam::AMIInterpolation::interpolateToSource
(
const Field<Type>& fld,
const CombineOp& cop,
const UList<Type>& defaultValues
) const
{
auto tresult = tmp<Field<Type>>::New(srcAddress_.size(), Zero);
interpolateToSource
(
fld,
multiplyWeightedOp<Type, CombineOp>(cop),
tresult.ref(),
defaultValues
);
return tresult;
}
template<class Type, class CombineOp>
Foam::tmp<Foam::Field<Type>> Foam::AMIInterpolation::interpolateToSource
(
const tmp<Field<Type>>& tFld,
const CombineOp& cop,
const UList<Type>& defaultValues
) const
{
return interpolateToSource(tFld(), cop, defaultValues);
}
template<class Type, class CombineOp>
Foam::tmp<Foam::Field<Type>> Foam::AMIInterpolation::interpolateToTarget
(
const Field<Type>& fld,
const CombineOp& cop,
const UList<Type>& defaultValues
) const
{
auto tresult = tmp<Field<Type>>::New(tgtAddress_.size(), Zero);
interpolateToTarget
(
fld,
multiplyWeightedOp<Type, CombineOp>(cop),
tresult.ref(),
defaultValues
);
return tresult;
}
template<class Type, class CombineOp>
Foam::tmp<Foam::Field<Type>> Foam::AMIInterpolation::interpolateToTarget
(
const tmp<Field<Type>>& tFld,
const CombineOp& cop,
const UList<Type>& defaultValues
) const
{
return interpolateToTarget(tFld(), cop, defaultValues);
}
template<class Type>
Foam::tmp<Foam::Field<Type>> Foam::AMIInterpolation::interpolateToSource
(
const Field<Type>& fld,
const UList<Type>& defaultValues
) const
{
return interpolateToSource(fld, plusEqOp<Type>(), defaultValues);
}
template<class Type>
Foam::tmp<Foam::Field<Type>> Foam::AMIInterpolation::interpolateToSource
(
const tmp<Field<Type>>& tFld,
const UList<Type>& defaultValues
) const
{
return interpolateToSource(tFld(), plusEqOp<Type>(), defaultValues);
}
template<class Type>
Foam::tmp<Foam::Field<Type>> Foam::AMIInterpolation::interpolateToTarget
(
const Field<Type>& fld,
const UList<Type>& defaultValues
) const
{
return interpolateToTarget(fld, plusEqOp<Type>(), defaultValues);
}
template<class Type>
Foam::tmp<Foam::Field<Type>> Foam::AMIInterpolation::interpolateToTarget
(
const tmp<Field<Type>>& tFld,
const UList<Type>& defaultValues
) const
{
return interpolateToTarget(tFld(), plusEqOp<Type>(), defaultValues);
}
// ************************************************************************* //

View File

@ -1,380 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2013-2016 OpenFOAM Foundation
Copyright (C) 2016-2018 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::AMIMethod
Description
Base class for Arbitrary Mesh Interface (AMI) methods
SourceFiles
AMIMethod.C
\*---------------------------------------------------------------------------*/
#ifndef AMIMethod_H
#define AMIMethod_H
#include "className.H"
#include "DynamicList.H"
#include "faceAreaIntersect.H"
#include "indexedOctree.H"
#include "treeDataPrimitivePatch.H"
#include "treeBoundBoxList.H"
#include "runTimeSelectionTables.H"
#include "pointList.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
template<class SourcePatch, class TargetPatch> class AMIInterpolation;
/*---------------------------------------------------------------------------*\
Class AMIMethod Declaration
\*---------------------------------------------------------------------------*/
template<class SourcePatch, class TargetPatch>
class AMIMethod
{
private:
// Private Member Functions
//- No copy construct
AMIMethod(const AMIMethod&) = delete;
//- No copy assignment
void operator=(const AMIMethod&) = delete;
// Parallel operations
//- Calculate if patches are on multiple processors
label calcDistribution
(
const SourcePatch& srcPatch,
const TargetPatch& tgtPatch
) const;
label calcOverlappingProcs
(
const List<treeBoundBoxList>& procBb,
const treeBoundBox& bb,
boolList& overlaps
) const;
void distributePatches
(
const mapDistribute& map,
const TargetPatch& pp,
const globalIndex& gi,
List<faceList>& faces,
List<pointField>& points,
List<labelList>& tgtFaceIDs
) const;
void distributeAndMergePatches
(
const mapDistribute& map,
const TargetPatch& tgtPatch,
const globalIndex& gi,
faceList& tgtFaces,
pointField& tgtPoints,
labelList& tgtFaceIDs
) const;
autoPtr<mapDistribute> calcProcMap
(
const SourcePatch& srcPatch,
const TargetPatch& tgtPatch
) const;
protected:
//- Local typedef to octree tree-type
typedef treeDataPrimitivePatch<TargetPatch> treeType;
// Protected data
//- Reference to source patch
const SourcePatch& srcPatch0_;
//- Reference to target patch
const TargetPatch& tgtPatch0_;
//- Demand-driven extended target mesh (distributed parallel usage)
autoPtr<TargetPatch> extendedTgtPatchPtr_;
//- Flag to indicate that the two patches are co-directional and
//- that the orientation of the target patch should be reversed
const bool reverseTarget_;
//- Flag to indicate that the two patches must be matched/an overlap
//- exists between them
const bool requireMatch_;
//- Labels of faces that are not overlapped by any target faces
//- (should be empty for correct functioning for fully covered AMIs)
labelList srcNonOverlap_;
//- Octree used to find face seeds
autoPtr<indexedOctree<treeType>> treePtr_;
//- Face triangulation mode
const faceAreaIntersect::triangulationMode triMode_;
//- Label of processor containing all meshes
//- Note: set to -1 if distributed
label singleMeshProc_;
mutable faceList newTgtFaces_;
mutable pointField newTgtPoints_;
// Protected Member Functions
// Helper functions
//- Create a map that extends tgtPatch so that it covers srcPatch
autoPtr<TargetPatch> createExtendedTgtPatch
(
const SourcePatch& srcPatch,
const TargetPatch& tgtPatch,
const globalIndex& globalTgtFaces,
autoPtr<mapDistribute>& mapPtr,
labelList& extendedTgtFaceIDs
) const;
//- Check AMI patch coupling
void checkPatches() const;
//- Initialise and return true if all ok
bool initialise
(
labelListList& srcAddress,
scalarListList& srcWeights,
labelListList& tgtAddress,
scalarListList& tgtWeights,
label& srcFacei,
label& tgtFacei
);
//- Write triangle intersection to OBJ file
void writeIntersectionOBJ
(
const scalar area,
const face& f1,
const face& f2,
const pointField& f1Points,
const pointField& f2Points
) const;
// Common AMI method functions
//- Reset the octree for the target patch face search
template<class PatchType>
autoPtr<indexedOctree<treeDataPrimitivePatch<PatchType>>>
createTree
(
const PatchType& patch
) const;
label findTargetFace
(
const label srcFacei,
const UList<label>& excludeFaces = UList<label>::null(),
const label srcFacePti = -1
) const;
//- Add faces neighbouring facei to the ID list
void appendNbrFaces
(
const label facei,
const TargetPatch& patch,
const DynamicList<label>& visitedFaces,
DynamicList<label>& faceIDs
) const;
//- Helper function to decompose a patch
template<class PatchType>
void triangulatePatch
(
const PatchType& patch,
List<DynamicList<face>>& tris,
List<scalar>& magSf
) const;
public:
//- Runtime type information
TypeName("AMIMethod");
//- Declare runtime constructor selection table
declareRunTimeSelectionTable
(
autoPtr,
AMIMethod,
components,
(
const SourcePatch& srcPatch,
const TargetPatch& tgtPatch,
const faceAreaIntersect::triangulationMode& triMode,
const bool reverseTarget,
const bool requireMatch
),
(
srcPatch,
tgtPatch,
triMode,
reverseTarget,
requireMatch
)
);
//- Construct from components
AMIMethod
(
const SourcePatch& srcPatch,
const TargetPatch& tgtPatch,
const faceAreaIntersect::triangulationMode& triMode,
const bool reverseTarget,
const bool requireMatch
);
//- Selector
static autoPtr<AMIMethod> New
(
const word& methodName,
const SourcePatch& srcPatch,
const TargetPatch& tgtPatch,
const faceAreaIntersect::triangulationMode& triMode,
const bool reverseTarget,
const bool requireMatch
);
//- Destructor
virtual ~AMIMethod() = default;
// Member Functions
// Access
//- Return const access to the source patch
inline const SourcePatch& srcPatch() const;
//- Return const access to the target patch
inline const TargetPatch& tgtPatch() const;
//- Return true if the patches are split across multiple processors
inline bool distributed() const;
//- Labels of faces that are not overlapped by any target faces
// Note: this should be empty for correct functioning
inline const labelList& srcNonOverlap() const;
//- Flag to indicate that interpolation patches are conformal
virtual bool conformal() const;
// Manipulation
//- Update addressing and weights
virtual bool calculate
(
labelListList& srcAddress,
scalarListList& srcWeights,
pointListList& srcCentroids,
labelListList& tgtAddress,
scalarListList& tgtWeights,
scalarList& srcMagSf,
scalarList& tgtMagSf,
autoPtr<mapDistribute>& srcMapPtr,
autoPtr<mapDistribute>& tgtMapPtr,
label srcFacei = -1,
label tgtFacei = -1
) = 0;
//- Normalise the weight. Can optionally subset addressing
//- (e.g. for mapNearest)
virtual void normaliseWeights
(
const bool verbose,
AMIInterpolation<SourcePatch, TargetPatch>& inter
) = 0;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#define makeAMIMethod(AMIType) \
\
typedef AMIMethod<AMIType::sourcePatchType,AMIType::targetPatchType> \
AMIMethod##AMIType; \
\
defineNamedTemplateTypeNameAndDebug(AMIMethod##AMIType, 0); \
defineTemplateRunTimeSelectionTable(AMIMethod##AMIType, components);
#define makeAMIMethodType(AMIType, Method) \
\
typedef Method<AMIType::sourcePatchType,AMIType::targetPatchType> \
Method##AMIType; \
\
defineNamedTemplateTypeNameAndDebug(Method##AMIType, 0); \
\
AMIMethod<AMIType::sourcePatchType,AMIType::targetPatchType>:: \
addcomponentsConstructorToTable<Method##AMIType> \
add##Method##AMIType##ConstructorToTable_;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#include "AMIMethodI.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "AMIMethod.C"
#include "AMIMethodNew.C"
#include "AMIMethodParallelOps.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -1,361 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "nearestFaceAMI.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
template<class SourcePatch, class TargetPatch>
Foam::autoPtr<Foam::mapDistribute>
Foam::nearestFaceAMI<SourcePatch, TargetPatch>::calcFaceMap
(
const List<nearestAndDist>& localInfo,
const SourcePatch& srcPatch,
const TargetPatch& tgtPatch
) const
{
// Generate the list of processor bounding boxes
List<boundBox> procBbs(Pstream::nProcs());
procBbs[Pstream::myProcNo()] =
boundBox(srcPatch.points(), srcPatch.meshPoints(), true);
Pstream::gatherList(procBbs);
Pstream::scatterList(procBbs);
// Identify which of my local tgt faces intersect with each processor bb
// within the current match's search distance
const pointField& tgtCcs = tgtPatch.faceCentres();
List<DynamicList<label>> dynSendMap(Pstream::nProcs());
forAll(localInfo, tgtFacei)
{
const scalar r2 = localInfo[tgtFacei].second();
// Construct local bounding box to test against processor bb
forAll(procBbs, proci)
{
if (proci != Pstream::myProcNo())
{
if (procBbs[proci].overlaps(tgtCcs[tgtFacei], r2))
{
dynSendMap[proci].append(tgtFacei);
}
}
}
}
// Convert dynamicList to labelList
labelListList sendMap(Pstream::nProcs());
forAll(sendMap, proci)
{
dynSendMap[proci].shrink();
sendMap[proci].transfer(dynSendMap[proci]);
if (debug)
{
Pout<< "send map - to proc " << proci << " sending "
<< sendMap[proci].size() << " elements" << endl;
}
}
return autoPtr<mapDistribute>::New(std::move(sendMap));
}
template<class SourcePatch, class TargetPatch>
Foam::autoPtr<Foam::mapDistribute>
Foam::nearestFaceAMI<SourcePatch, TargetPatch>::calcDistributed
(
const SourcePatch& src,
const TargetPatch& tgt,
labelListList& srcToTgtAddr,
scalarListList& srcToTgtWght
) const
{
const auto tgtTreePtr = this->createTree(tgt);
const auto& tgtTree = tgtTreePtr();
// Create global indexing for each patch
globalIndex globalTgtCells(src.size());
// First pass: determine local matches
// Identify local nearest matches
pointField srcCcs(src.faceCentres());
List<nearestAndDist> localInfo(src.size());
forAll(srcCcs, srcCelli)
{
const point& srcCc = srcCcs[srcCelli];
pointIndexHit& test = localInfo[srcCelli].first();
test = tgtTree.findNearest(srcCc, GREAT);
if (test.hit())
{
// With a search radius2 of GREAT all cells should receive a hit
localInfo[srcCelli].second() = magSqr(srcCc - test.hitPoint());
test.setIndex(globalTgtCells.toGlobal(test.index()));
}
}
// Second pass: determine remote matches
autoPtr<mapDistribute> mapPtr = calcFaceMap(localInfo, src, tgt);
mapDistribute& map = mapPtr();
List<nearestAndDist> remoteInfo(localInfo);
map.distribute(remoteInfo);
// Note: re-using srcCcs
map.distribute(srcCcs);
// Test remote target cells against local source cells
nearestAndDist testInfo;
pointIndexHit& test = testInfo.first();
forAll(remoteInfo, i)
{
test = tgtTree.findNearest(srcCcs[i], remoteInfo[i].second());
if (test.hit())
{
testInfo.first().setIndex
(
globalTgtCells.toGlobal(test.index())
);
testInfo.second() = magSqr(test.hitPoint() - srcCcs[i]);
nearestEqOp()(remoteInfo[i], testInfo);
}
}
// Send back to originating processor. Choose best if sent to multiple
// processors. Note that afterwards all unused entries have the unique
// value nearestZero (distance < 0). This is used later on to see if
// the sample was sent to any processor.
const nearestAndDist nearestZero(pointIndexHit(), -GREAT);
mapDistributeBase::distribute
(
Pstream::commsTypes::nonBlocking,
List<labelPair>(0),
src.size(),
map.constructMap(),
map.constructHasFlip(),
map.subMap(),
map.subHasFlip(),
remoteInfo,
nearestEqOp(),
noOp(), // no flipping
nearestZero
);
// Third pass: combine local and remote info and filter out any
// connections that are further away than threshold distance squared
srcToTgtAddr.setSize(src.size());
srcToTgtWght.setSize(src.size());
forAll(srcToTgtAddr, srcCelli)
{
nearestEqOp()(localInfo[srcCelli], remoteInfo[srcCelli]);
if (localInfo[srcCelli].second() < maxDistance2_)
{
const label tgtCelli = localInfo[srcCelli].first().index();
srcToTgtAddr[srcCelli] = labelList(1, tgtCelli);
srcToTgtWght[srcCelli] = scalarList(1, 1.0);
}
}
List<Map<label>> cMap;
return autoPtr<mapDistribute>::New(globalTgtCells, srcToTgtAddr, cMap);
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
template<class SourcePatch, class TargetPatch>
Foam::nearestFaceAMI<SourcePatch, TargetPatch>::nearestFaceAMI
(
const SourcePatch& srcPatch,
const TargetPatch& tgtPatch,
const faceAreaIntersect::triangulationMode& triMode,
const bool reverseTarget,
const bool requireMatch
)
:
AMIMethod<SourcePatch, TargetPatch>
(
srcPatch,
tgtPatch,
triMode,
reverseTarget,
requireMatch
),
maxDistance2_(GREAT)
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class SourcePatch, class TargetPatch>
bool Foam::nearestFaceAMI<SourcePatch, TargetPatch>::calculate
(
labelListList& srcAddress,
scalarListList& srcWeights,
pointListList& srcCentroids,
labelListList& tgtAddress,
scalarListList& tgtWeights,
scalarList& srcMagSf,
scalarList& tgtMagSf,
autoPtr<mapDistribute>& srcMapPtr,
autoPtr<mapDistribute>& tgtMapPtr,
label srcFacei,
label tgtFacei
)
{
bool symmetric_ = true;
if (this->distributed())
{
tgtMapPtr =
calcDistributed
(
this->srcPatch0_,
this->tgtPatch0_,
srcAddress,
srcWeights
);
if (symmetric_)
{
srcMapPtr =
calcDistributed
(
this->tgtPatch0_,
this->srcPatch0_,
tgtAddress,
tgtWeights
);
}
}
else
{
srcAddress.setSize(this->srcPatch0_.size());
srcWeights.setSize(this->srcPatch0_.size());
if (symmetric_)
{
tgtAddress.setSize(this->tgtPatch0_.size());
tgtWeights.setSize(this->tgtPatch0_.size());
}
const pointField& srcCcs = this->srcPatch0_.faceCentres();
const pointField& tgtCcs = this->tgtPatch0_.faceCentres();
const auto tgtTreePtr = this->createTree(this->tgtPatch0_);
const auto& tgtTree = tgtTreePtr();
forAll(srcCcs, srcFacei)
{
const point& srcCc = srcCcs[srcFacei];
const pointIndexHit hit = tgtTree.findNearest(srcCc, GREAT);
if
(
hit.hit()
&& (magSqr(srcCc - tgtCcs[hit.index()]) < maxDistance2_)
)
{
label tgtFacei = hit.index();
srcAddress[srcFacei] = labelList(1, tgtFacei);
srcWeights[srcFacei] = scalarList(1, 1.0);
if (symmetric_)
{
tgtAddress[tgtFacei] = labelList(1, srcFacei);
tgtWeights[tgtFacei] = scalarList(1, 1.0);
}
}
else
{
if (debug)
{
WarningInFunction
<< "Unable to find target face for source face "
<< srcFacei << endl;
}
}
}
if (symmetric_)
{
const auto srcTreePtr = this->createTree(this->srcPatch0_);
const auto& srcTree = srcTreePtr();
// Check that all source cells have connections and populate any
// missing entries
forAll(tgtWeights, tgtCelli)
{
if (tgtAddress[tgtCelli].empty())
{
const point& tgtCc = tgtCcs[tgtCelli];
pointIndexHit hit = srcTree.findNearest(tgtCc, GREAT);
if
(
hit.hit()
&& (magSqr(tgtCc - srcCcs[hit.index()]) < maxDistance2_)
)
{
tgtAddress[tgtCelli] = labelList(1, hit.index());
tgtWeights[tgtCelli] = scalarList(1, 1.0);
}
}
else
{
if (debug)
{
WarningInFunction
<< "Unable to find source face for target face "
<< tgtCelli << endl;
}
}
}
}
}
return true;
}
template<class SourcePatch, class TargetPatch>
void Foam::nearestFaceAMI<SourcePatch, TargetPatch>::normaliseWeights
(
const bool verbose,
AMIInterpolation<SourcePatch, TargetPatch>& inter
)
{
// Do nothing - weights already 1-to-1 and normalised
}
// ************************************************************************* //

View File

@ -1,46 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2013 OpenFOAM Foundation
-------------------------------------------------------------------------------
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 "AMIPatchToPatchInterpolation.H"
#include "AMIMethod.H"
#include "nearestFaceAMI.H"
#include "faceAreaWeightAMI.H"
#include "partialFaceAreaWeightAMI.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
makeAMIMethod(AMIPatchToPatchInterpolation);
makeAMIMethodType(AMIPatchToPatchInterpolation, nearestFaceAMI);
makeAMIMethodType(AMIPatchToPatchInterpolation, faceAreaWeightAMI);
makeAMIMethodType(AMIPatchToPatchInterpolation, partialFaceAreaWeightAMI);
}
// ************************************************************************* //

View File

@ -30,14 +30,12 @@ License
#define AMIPatchToPatchInterpolation_H #define AMIPatchToPatchInterpolation_H
#include "AMIInterpolation.H" #include "AMIInterpolation.H"
#include "primitivePatch.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam namespace Foam
{ {
typedef AMIInterpolation<primitivePatch, primitivePatch> typedef AMIInterpolation AMIPatchToPatchInterpolation;
AMIPatchToPatchInterpolation;
} }
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -26,17 +26,23 @@ License
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#include "AMIMethod.H" #include "advancingFrontAMI.H"
#include "meshTools.H" #include "meshTools.H"
#include "mapDistribute.H" #include "mapDistribute.H"
#include "unitConversion.H" #include "unitConversion.H"
#include "findNearestMaskedOp.H" #include "findNearestMaskedOp.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(advancingFrontAMI, 0);
}
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * // // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
template<class SourcePatch, class TargetPatch> void Foam::advancingFrontAMI::checkPatches() const
void Foam::AMIMethod<SourcePatch, TargetPatch>::checkPatches() const
{ {
const auto& src = srcPatch(); const auto& src = srcPatch();
const auto& tgt = tgtPatch(); const auto& tgt = tgtPatch();
@ -75,101 +81,68 @@ void Foam::AMIMethod<SourcePatch, TargetPatch>::checkPatches() const
} }
template<class SourcePatch, class TargetPatch> void Foam::advancingFrontAMI::createExtendedTgtPatch()
Foam::autoPtr<TargetPatch>
Foam::AMIMethod<SourcePatch, TargetPatch>::createExtendedTgtPatch
(
const SourcePatch& srcPatch,
const TargetPatch& tgtPatch,
const globalIndex& globalTgtFaces,
autoPtr<mapDistribute>& mapPtr,
labelList& extendedTgtFaceIDs
) const
{ {
// Create a representation of the src mesh that is extended to overlap the
// tgt mesh
// Create processor map of extended cells. This map gets (possibly // Create processor map of extended cells. This map gets (possibly
// remote) cells from the src mesh such that they (together) cover // remote) cells from the src mesh such that they (together) cover
// all of tgt // all of tgt
mapPtr = calcProcMap(srcPatch, tgtPatch); extendedTgtMapPtr_.reset(calcProcMap(srcPatch0(), tgtPatch0()));
const mapDistribute& map = mapPtr(); const mapDistribute& map = extendedTgtMapPtr_();
// Create new target patch that fully encompasses source patch // Original faces from tgtPatch
// Note: in globalIndexing since might be remote
// Faces and points globalIndex globalTgtFaces(tgtPatch0().size());
// faceList newTgtFaces_;
// pointField newTgtPoints_;
// Original faces from tgtPatch (in globalIndexing since might be
// remote)
distributeAndMergePatches distributeAndMergePatches
( (
map, map,
tgtPatch, tgtPatch0(),
globalTgtFaces, globalTgtFaces,
newTgtFaces_, extendedTgtFaces_,
newTgtPoints_, extendedTgtPoints_,
extendedTgtFaceIDs extendedTgtFaceIDs_
); );
return autoPtr<TargetPatch>::New // Create a representation of the tgt patch that is extended to overlap
// the src patch
extendedTgtPatchPtr_.reset
( (
SubList<face> autoPtr<primitivePatch>::New
( (
newTgtFaces_, SubList<face>(extendedTgtFaces_),
newTgtFaces_.size() extendedTgtPoints_
), )
newTgtPoints_
); );
} }
template<class SourcePatch, class TargetPatch> bool Foam::advancingFrontAMI::initialiseWalk(label& srcFacei, label& tgtFacei)
bool Foam::AMIMethod<SourcePatch, TargetPatch>::initialise
(
labelListList& srcAddress,
scalarListList& srcWeights,
labelListList& tgtAddress,
scalarListList& tgtWeights,
label& srcFacei,
label& tgtFacei
)
{ {
const auto& src = srcPatch(); const auto& src = this->srcPatch();
const auto& tgt = tgtPatch(); const auto& tgt = this->tgtPatch();
checkPatches(); bool foundFace = false;
// Set initial sizes for weights and addressing - must be done even if
// returns false below
srcAddress.setSize(src.size());
srcWeights.setSize(srcAddress.size());
tgtAddress.setSize(tgt.size());
tgtWeights.setSize(tgtAddress.size());
// Check that patch sizes are valid // Check that patch sizes are valid
if (!src.size()) if (!src.size())
{ {
return false; return foundFace;
} }
else if (!tgt.size()) else if (!tgt.size())
{ {
WarningInFunction WarningInFunction
<< src.size() << " source faces but no target faces" << endl; << src.size() << " source faces but no target faces" << endl;
return false; return foundFace;
} }
// Reset the octree // Reset the octree
treePtr_.reset(createTree<TargetPatch>(tgtPatch())); treePtr_.reset(createTree(tgt));
// Find initial face match using brute force/octree search // Find initial face match using brute force/octree search
if ((srcFacei == -1) || (tgtFacei == -1)) if ((srcFacei == -1) || (tgtFacei == -1))
{ {
srcFacei = 0; srcFacei = 0;
tgtFacei = 0; tgtFacei = 0;
bool foundFace = false;
forAll(src, facei) forAll(src, facei)
{ {
tgtFacei = findTargetFace(facei); tgtFacei = findTargetFace(facei);
@ -190,7 +163,7 @@ bool Foam::AMIMethod<SourcePatch, TargetPatch>::initialise
<< abort(FatalError); << abort(FatalError);
} }
return false; return foundFace;
} }
} }
@ -203,8 +176,7 @@ bool Foam::AMIMethod<SourcePatch, TargetPatch>::initialise
} }
template<class SourcePatch, class TargetPatch> void Foam::advancingFrontAMI::writeIntersectionOBJ
void Foam::AMIMethod<SourcePatch, TargetPatch>::writeIntersectionOBJ
( (
const scalar area, const scalar area,
const face& f1, const face& f1,
@ -255,37 +227,7 @@ void Foam::AMIMethod<SourcePatch, TargetPatch>::writeIntersectionOBJ
} }
template<class SourcePatch, class TargetPatch> Foam::label Foam::advancingFrontAMI::findTargetFace
template<class PatchType>
Foam::autoPtr<Foam::indexedOctree<Foam::treeDataPrimitivePatch<PatchType>>>
Foam::AMIMethod<SourcePatch, TargetPatch>::createTree
(
const PatchType& patch
) const
{
typedef treeDataPrimitivePatch<PatchType> PatchTreeType;
treeBoundBox bb(patch.points(), patch.meshPoints());
bb.inflate(0.01);
return autoPtr<indexedOctree<PatchTreeType>>::New
(
PatchTreeType
(
false,
patch,
indexedOctree<PatchTreeType>::perturbTol()
),
bb, // overall search domain
8, // maxLevel
10, // leaf size
3.0 // duplicity
);
}
template<class SourcePatch, class TargetPatch>
Foam::label Foam::AMIMethod<SourcePatch, TargetPatch>::findTargetFace
( (
const label srcFacei, const label srcFacei,
const UList<label>& excludeFaces, const UList<label>& excludeFaces,
@ -299,9 +241,9 @@ Foam::label Foam::AMIMethod<SourcePatch, TargetPatch>::findTargetFace
const pointField& srcPts = src.points(); const pointField& srcPts = src.points();
const face& srcFace = src[srcFacei]; const face& srcFace = src[srcFacei];
findNearestMaskedOp<TargetPatch> fnOp(*treePtr_, excludeFaces); findNearestMaskedOp<primitivePatch> fnOp(*treePtr_, excludeFaces);
boundBox bb(srcPts, srcFace, false); const boundBox bb(srcPts, srcFace, false);
const point srcPt = const point srcPt =
srcFacePti == -1 ? bb.centre() : srcPts[srcFace[srcFacePti]]; srcFacePti == -1 ? bb.centre() : srcPts[srcFace[srcFacePti]];
@ -325,11 +267,10 @@ Foam::label Foam::AMIMethod<SourcePatch, TargetPatch>::findTargetFace
} }
template<class SourcePatch, class TargetPatch> void Foam::advancingFrontAMI::appendNbrFaces
void Foam::AMIMethod<SourcePatch, TargetPatch>::appendNbrFaces
( (
const label facei, const label facei,
const TargetPatch& patch, const primitivePatch& patch,
const DynamicList<label>& visitedFaces, const DynamicList<label>& visitedFaces,
DynamicList<label>& faceIDs DynamicList<label>& faceIDs
) const ) const
@ -341,30 +282,8 @@ void Foam::AMIMethod<SourcePatch, TargetPatch>::appendNbrFaces
// Filter out faces already visited from face neighbours // Filter out faces already visited from face neighbours
for (const label nbrFacei : nbrFaces) for (const label nbrFacei : nbrFaces)
{ {
bool valid = true;
for (const label visitedFacei : visitedFaces)
{
if (nbrFacei == visitedFacei)
{
valid = false;
break;
}
}
if (valid)
{
for (const label testFacei : faceIDs)
{
if (nbrFacei == testFacei)
{
valid = false;
break;
}
}
}
// Prevent addition of face if it is not on the same plane-ish // Prevent addition of face if it is not on the same plane-ish
if (valid) if (!visitedFaces.found(nbrFacei) && !faceIDs.found(nbrFacei))
{ {
const vector& n1 = patch.faceNormals()[facei]; const vector& n1 = patch.faceNormals()[facei];
const vector& n2 = patch.faceNormals()[nbrFacei]; const vector& n2 = patch.faceNormals()[nbrFacei];
@ -380,11 +299,9 @@ void Foam::AMIMethod<SourcePatch, TargetPatch>::appendNbrFaces
} }
template<class SourcePatch, class TargetPatch> void Foam::advancingFrontAMI::triangulatePatch
template<class PatchType>
void Foam::AMIMethod<SourcePatch, TargetPatch>::triangulatePatch
( (
const PatchType& patch, const primitivePatch& patch,
List<DynamicList<face>>& tris, List<DynamicList<face>>& tris,
List<scalar>& magSf List<scalar>& magSf
) const ) const
@ -396,6 +313,8 @@ void Foam::AMIMethod<SourcePatch, TargetPatch>::triangulatePatch
// Using methods that index into existing points // Using methods that index into existing points
forAll(patch, facei) forAll(patch, facei)
{ {
tris[facei].clear();
switch (triMode_) switch (triMode_)
{ {
case faceAreaIntersect::tmFan: case faceAreaIntersect::tmFan:
@ -428,34 +347,114 @@ void Foam::AMIMethod<SourcePatch, TargetPatch>::triangulatePatch
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
template<class SourcePatch, class TargetPatch> Foam::advancingFrontAMI::advancingFrontAMI
Foam::AMIMethod<SourcePatch, TargetPatch>::AMIMethod
( (
const SourcePatch& srcPatch, const dictionary& dict,
const TargetPatch& tgtPatch, const bool reverseTarget
const faceAreaIntersect::triangulationMode& triMode,
const bool reverseTarget,
const bool requireMatch
) )
: :
srcPatch0_(srcPatch), AMIInterpolation(dict, reverseTarget),
tgtPatch0_(tgtPatch), srcTris_(),
tgtTris_(),
extendedTgtPatchPtr_(nullptr), extendedTgtPatchPtr_(nullptr),
reverseTarget_(reverseTarget), extendedTgtFaces_(),
requireMatch_(requireMatch), extendedTgtPoints_(),
extendedTgtFaceIDs_(),
extendedTgtMapPtr_(nullptr),
srcNonOverlap_(), srcNonOverlap_(),
triMode_(triMode), triMode_
singleMeshProc_(calcDistribution(srcPatch, tgtPatch)) (
{ faceAreaIntersect::triangulationModeNames_.getOrDefault
// Note: setting srcMagSf and tgtMagSf to 1 by default for 1-to-1 methods (
// - others will need to overwrite as necessary "triMode",
} dict,
faceAreaIntersect::tmMesh
)
)
{}
Foam::advancingFrontAMI::advancingFrontAMI
(
const bool requireMatch,
const bool reverseTarget,
const scalar lowWeightCorrection,
const faceAreaIntersect::triangulationMode triMode
)
:
AMIInterpolation(requireMatch, reverseTarget, lowWeightCorrection),
srcTris_(),
tgtTris_(),
extendedTgtPatchPtr_(nullptr),
extendedTgtFaces_(),
extendedTgtPoints_(),
extendedTgtFaceIDs_(),
extendedTgtMapPtr_(nullptr),
srcNonOverlap_(),
triMode_(triMode)
{}
Foam::advancingFrontAMI::advancingFrontAMI(const advancingFrontAMI& ami)
:
AMIInterpolation(ami),
srcTris_(),
tgtTris_(),
extendedTgtPatchPtr_(nullptr),
extendedTgtFaces_(),
extendedTgtPoints_(),
extendedTgtFaceIDs_(),
extendedTgtMapPtr_(nullptr),
srcNonOverlap_(),
triMode_(ami.triMode_)
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class SourcePatch, class TargetPatch> bool Foam::advancingFrontAMI::calculate
bool Foam::AMIMethod<SourcePatch, TargetPatch>::conformal() const (
const primitivePatch& srcPatch,
const primitivePatch& tgtPatch,
const autoPtr<searchableSurface>& surfPtr
)
{
if (AMIInterpolation::calculate(srcPatch, tgtPatch, surfPtr))
{
// Create a representation of the target patch that covers the source patch
if (distributed())
{
createExtendedTgtPatch();
}
const auto& src = this->srcPatch();
const auto& tgt = this->tgtPatch();
// Initialise area magnitudes
srcMagSf_.setSize(src.size(), 1.0);
tgtMagSf_.setSize(tgt.size(), 1.0);
// Source and target patch triangulations
triangulatePatch(src, srcTris_, srcMagSf_);
triangulatePatch(tgt, tgtTris_, tgtMagSf_);
checkPatches();
// Set initial sizes for weights and addressing - must be done even if
// returns false below
srcAddress_.setSize(src.size());
srcWeights_.setSize(src.size());
tgtAddress_.setSize(tgt.size());
tgtWeights_.setSize(tgt.size());
return true;
}
return false;
}
bool Foam::advancingFrontAMI::conformal() const
{ {
return true; return true;
} }

View File

@ -0,0 +1,271 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2013-2016 OpenFOAM Foundation
Copyright (C) 2016-2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::advancingFrontAMI
Description
Base class for Arbitrary Mesh Interface (AMI) methods
SourceFiles
advancingFrontAMI.C
\*---------------------------------------------------------------------------*/
#ifndef advancingFrontAMI_H
#define advancingFrontAMI_H
#include "className.H"
#include "DynamicList.H"
#include "faceAreaIntersect.H"
#include "pointList.H"
#include "AMIInterpolation.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class advancingFrontAMI Declaration
\*---------------------------------------------------------------------------*/
class advancingFrontAMI
:
public AMIInterpolation
{
private:
// Private Member Functions
//- No copy assignment
void operator=(const advancingFrontAMI&) = delete;
// Parallel operations
label calcOverlappingProcs
(
const List<treeBoundBoxList>& procBb,
const treeBoundBox& bb,
boolList& overlaps
) const;
void distributePatches
(
const mapDistribute& map,
const primitivePatch& pp,
const globalIndex& gi,
List<faceList>& faces,
List<pointField>& points,
List<labelList>& tgtFaceIDs
) const;
void distributeAndMergePatches
(
const mapDistribute& map,
const primitivePatch& tgtPatch,
const globalIndex& gi,
faceList& tgtFaces,
pointField& tgtPoints,
labelList& tgtFaceIDs
) const;
autoPtr<mapDistribute> calcProcMap
(
const primitivePatch& srcPatch,
const primitivePatch& tgtPatch
) const;
protected:
// Protected data
//- Storage for src-side triangle decomposition
List<DynamicList<face>> srcTris_;
//- Storage for tgt-side triangle decomposition
List<DynamicList<face>> tgtTris_;
//- Demand-driven extended target mesh (distributed parallel usage)
autoPtr<primitivePatch> extendedTgtPatchPtr_;
//- Extended patch faces
faceList extendedTgtFaces_;
//- Extended patch points
pointField extendedTgtPoints_;
//- Extended patch face IDs
labelList extendedTgtFaceIDs_;
//- Extended patch map
autoPtr<mapDistribute> extendedTgtMapPtr_;
//- Labels of faces that are not overlapped by any target faces
//- (should be empty for correct functioning for fully covered AMIs)
labelList srcNonOverlap_;
//- Octree used to find face seeds
autoPtr<indexedOctree<treeType>> treePtr_;
//- Face triangulation mode
const faceAreaIntersect::triangulationMode triMode_;
// Protected Member Functions
// Helper functions
//- Create a map that extends tgtPatch so that it covers srcPatch
void createExtendedTgtPatch();
//- Check AMI patch coupling
void checkPatches() const;
virtual bool calculate
(
const primitivePatch& srcPatch,
const primitivePatch& tgtPatch,
const autoPtr<searchableSurface>& surfPtr = nullptr
);
//- Initialise walk and return true if all ok
bool initialiseWalk
(
label& srcFacei,
label& tgtFacei
);
//- Write triangle intersection to OBJ file
void writeIntersectionOBJ
(
const scalar area,
const face& f1,
const face& f2,
const pointField& f1Points,
const pointField& f2Points
) const;
// Common AMI method functions
label findTargetFace
(
const label srcFacei,
const UList<label>& excludeFaces = UList<label>::null(),
const label srcFacePti = -1
) const;
//- Add faces neighbouring facei to the ID list
void appendNbrFaces
(
const label facei,
const primitivePatch& patch,
const DynamicList<label>& visitedFaces,
DynamicList<label>& faceIDs
) const;
//- Helper function to decompose a patch
void triangulatePatch
(
const primitivePatch& patch,
List<DynamicList<face>>& tris,
List<scalar>& magSf
) const;
public:
//- Runtime type information
TypeName("advancingFrontAMI");
// Constructors
//- Construct from components
advancingFrontAMI
(
const dictionary& dict,
const bool reverseTarget
);
//- Construct from components
advancingFrontAMI
(
const bool requireMatch = true,
const bool reverseTarget = false,
const scalar lowWeightCorrection = -1,
const faceAreaIntersect::triangulationMode triMode =
faceAreaIntersect::tmMesh
);
//- Construct as copy
advancingFrontAMI(const advancingFrontAMI& ami);
//- Construct and return a clone
virtual autoPtr<AMIInterpolation> clone() const
{
return autoPtr<AMIInterpolation>(new advancingFrontAMI(*this));
}
//- Destructor
virtual ~advancingFrontAMI() = default;
// Member Functions
//- Return const access to the source patch
inline const primitivePatch& srcPatch() const;
//- Return const access to the target patch
inline const primitivePatch& tgtPatch() const;
//- Labels of faces that are not overlapped by any target faces
// Note: this should be empty for correct functioning
inline const labelList& srcNonOverlap() const;
//- Flag to indicate that interpolation patches are conformal, i.e.
//- should fully cover each other
virtual bool conformal() const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#include "advancingFrontAMII.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com \\ / A nd | www.openfoam.com
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2013 OpenFOAM Foundation Copyright (C) 2020 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -25,37 +25,38 @@ License
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
template<class SourcePatch, class TargetPatch> inline const Foam::primitivePatch& Foam::advancingFrontAMI::srcPatch() const
inline const SourcePatch&
Foam::AMIMethod<SourcePatch, TargetPatch>::srcPatch() const
{ {
return srcPatch0_; if (!tsrcPatch0_.valid())
{
FatalErrorInFunction
<< "tsrcPatch0_ not allocated"
<< abort(FatalError);
}
return tsrcPatch0_();
} }
template<class SourcePatch, class TargetPatch> inline const Foam::primitivePatch& Foam::advancingFrontAMI::tgtPatch() const
inline const TargetPatch&
Foam::AMIMethod<SourcePatch, TargetPatch>::tgtPatch() const
{ {
if (extendedTgtPatchPtr_) if (extendedTgtPatchPtr_)
{ {
return extendedTgtPatchPtr_(); return extendedTgtPatchPtr_();
} }
return tgtPatch0_; if (!ttgtPatch0_.valid())
{
FatalErrorInFunction
<< "srcPatch0Ptr not allocated"
<< abort(FatalError);
}
return ttgtPatch0_();
} }
template<class SourcePatch, class TargetPatch> inline const Foam::labelList& Foam::advancingFrontAMI::srcNonOverlap() const
bool Foam::AMIMethod<SourcePatch, TargetPatch>::distributed() const
{
return singleMeshProc_ == -1;
}
template<class SourcePatch, class TargetPatch>
inline const Foam::labelList&
Foam::AMIMethod<SourcePatch, TargetPatch>::srcNonOverlap() const
{ {
return srcNonOverlap_; return srcNonOverlap_;
} }

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2018-2020 OpenCFD Ltd. Copyright (C) 2018 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -25,60 +25,15 @@ License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#include "advancingFrontAMI.H"
#include "mergePoints.H" #include "mergePoints.H"
#include "mapDistribute.H" #include "mapDistribute.H"
#include "AABBTree.H" #include "AABBTree.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
template<class SourcePatch, class TargetPatch> Foam::label Foam::advancingFrontAMI::calcOverlappingProcs
Foam::label Foam::AMIMethod<SourcePatch, TargetPatch>::calcDistribution
(
const SourcePatch& srcPatch,
const TargetPatch& tgtPatch
) const
{
label proci = 0;
if (Pstream::parRun())
{
labelList facesPresentOnProc(Pstream::nProcs(), Zero);
if ((srcPatch.size() > 0) || (tgtPatch.size() > 0))
{
facesPresentOnProc[Pstream::myProcNo()] = 1;
}
else
{
facesPresentOnProc[Pstream::myProcNo()] = 0;
}
Pstream::gatherList(facesPresentOnProc);
Pstream::scatterList(facesPresentOnProc);
label nHaveFaces = sum(facesPresentOnProc);
if (nHaveFaces > 1)
{
proci = -1;
DebugInFunction
<< "AMI split across multiple processors" << endl;
}
else if (nHaveFaces == 1)
{
proci = facesPresentOnProc.find(1);
DebugInFunction
<< "AMI local to processor" << proci << endl;
}
}
// Either not parallel or no faces on any processor
return proci;
}
template<class SourcePatch, class TargetPatch>
Foam::label Foam::AMIMethod<SourcePatch, TargetPatch>::calcOverlappingProcs
( (
const List<treeBoundBoxList>& procBb, const List<treeBoundBoxList>& procBb,
const treeBoundBox& bb, const treeBoundBox& bb,
@ -109,11 +64,10 @@ Foam::label Foam::AMIMethod<SourcePatch, TargetPatch>::calcOverlappingProcs
} }
template<class SourcePatch, class TargetPatch> void Foam::advancingFrontAMI::distributePatches
void Foam::AMIMethod<SourcePatch, TargetPatch>::distributePatches
( (
const mapDistribute& map, const mapDistribute& map,
const TargetPatch& pp, const primitivePatch& pp,
const globalIndex& gi, const globalIndex& gi,
List<faceList>& faces, List<faceList>& faces,
List<pointField>& points, List<pointField>& points,
@ -194,12 +148,10 @@ void Foam::AMIMethod<SourcePatch, TargetPatch>::distributePatches
} }
template<class SourcePatch, class TargetPatch> void Foam::advancingFrontAMI::distributeAndMergePatches
void Foam::AMIMethod<SourcePatch, TargetPatch>::
distributeAndMergePatches
( (
const mapDistribute& map, const mapDistribute& map,
const TargetPatch& tgtPatch, const primitivePatch& tgtPatch,
const globalIndex& gi, const globalIndex& gi,
faceList& tgtFaces, faceList& tgtFaces,
pointField& tgtPoints, pointField& tgtPoints,
@ -308,12 +260,10 @@ distributeAndMergePatches
} }
template<class SourcePatch, class TargetPatch> Foam::autoPtr<Foam::mapDistribute> Foam::advancingFrontAMI::calcProcMap
Foam::autoPtr<Foam::mapDistribute>
Foam::AMIMethod<SourcePatch, TargetPatch>::calcProcMap
( (
const SourcePatch& srcPatch, const primitivePatch& srcPatch,
const TargetPatch& tgtPatch const primitivePatch& tgtPatch
) const ) const
{ {
// Get decomposition of patch // Get decomposition of patch

View File

@ -29,41 +29,20 @@ License
#include "faceAreaWeightAMI.H" #include "faceAreaWeightAMI.H"
#include "profiling.H" #include "profiling.H"
#include "OBJstream.H" #include "OBJstream.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(faceAreaWeightAMI, 0);
addToRunTimeSelectionTable(AMIInterpolation, faceAreaWeightAMI, dict);
addToRunTimeSelectionTable(AMIInterpolation, faceAreaWeightAMI, component);
}
// * * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * // // * * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * //
template<class SourcePatch, class TargetPatch> /*
void Foam::faceAreaWeightAMI<SourcePatch, TargetPatch>::initGeom
(
const globalIndex& globalTgtFaces,
labelList& extendedTgtFaceIDs
)
{
// Create a representation of the target patch that covers the source patch
if (this->distributed())
{
this->extendedTgtPatchPtr_ =
this->createExtendedTgtPatch
(
this->srcPatch0_,
this->tgtPatch0_,
globalTgtFaces,
extendedTgtMapPtr_,
extendedTgtFaceIDs
);
}
const auto& src = this->srcPatch();
const auto& tgt = this->tgtPatch();
// Initialise area magnitudes
srcMagSf_.setSize(src.size(), 1.0);
tgtMagSf_.setSize(tgt.size(), 1.0);
// Source and target patch triangulations
this->triangulatePatch(src, srcTris_, srcMagSf_);
this->triangulatePatch(tgt, tgtTris_, tgtMagSf_);
if (debug) if (debug)
{ {
static label nAMI = 0; static label nAMI = 0;
@ -99,11 +78,10 @@ void Foam::faceAreaWeightAMI<SourcePatch, TargetPatch>::initGeom
++nAMI; ++nAMI;
} }
} */
template<class SourcePatch, class TargetPatch> void Foam::faceAreaWeightAMI::calcAddressing
void Foam::faceAreaWeightAMI<SourcePatch, TargetPatch>::calcAddressing
( (
List<DynamicList<label>>& srcAddr, List<DynamicList<label>>& srcAddr,
List<DynamicList<scalar>>& srcWght, List<DynamicList<scalar>>& srcWght,
@ -116,27 +94,28 @@ void Foam::faceAreaWeightAMI<SourcePatch, TargetPatch>::calcAddressing
{ {
addProfiling(ami, "faceAreaWeightAMI::calcAddressing"); addProfiling(ami, "faceAreaWeightAMI::calcAddressing");
// construct weights and addressing // Construct weights and addressing
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
label nFacesRemaining = srcAddr.size(); label nFacesRemaining = srcAddr.size();
// list of tgt face neighbour faces // List of tgt face neighbour faces
DynamicList<label> nbrFaces(10); DynamicList<label> nbrFaces(10);
// list of faces currently visited for srcFacei to avoid multiple hits // List of faces currently visited for srcFacei to avoid multiple hits
DynamicList<label> visitedFaces(10); DynamicList<label> visitedFaces(10);
// list to keep track of tgt faces used to seed src faces // List to keep track of tgt faces used to seed src faces
labelList seedFaces(nFacesRemaining, -1); labelList seedFaces(nFacesRemaining, -1);
seedFaces[srcFacei] = tgtFacei; seedFaces[srcFacei] = tgtFacei;
// list to keep track of whether src face can be mapped // List to keep track of whether src face can be mapped
bitSet mapFlag(nFacesRemaining, true); bitSet mapFlag(nFacesRemaining, true);
// reset starting seed // Reset starting seed
label startSeedi = 0; label startSeedi = 0;
bool continueWalk = true;
DynamicList<label> nonOverlapFaces; DynamicList<label> nonOverlapFaces;
do do
{ {
@ -161,34 +140,30 @@ void Foam::faceAreaWeightAMI<SourcePatch, TargetPatch>::calcAddressing
mapFlag.unset(srcFacei); mapFlag.unset(srcFacei);
nFacesRemaining--;
if (!faceProcessed) if (!faceProcessed)
{ {
nonOverlapFaces.append(srcFacei); nonOverlapFaces.append(srcFacei);
} }
// choose new src face from current src face neighbour // Choose new src face from current src face neighbour
if (nFacesRemaining > 0) continueWalk = setNextFaces
{ (
setNextFaces startSeedi,
( srcFacei,
startSeedi, tgtFacei,
srcFacei, mapFlag,
tgtFacei, seedFaces,
mapFlag, visitedFaces,
seedFaces, requireMatch_ && (lowWeightCorrection_ < 0)
visitedFaces // pass in nonOverlapFaces for failed tree search?
); );
} } while (continueWalk);
} while (nFacesRemaining > 0);
this->srcNonOverlap_.transfer(nonOverlapFaces); srcNonOverlap_.transfer(nonOverlapFaces);
} }
template<class SourcePatch, class TargetPatch> bool Foam::faceAreaWeightAMI::processSourceFace
bool Foam::faceAreaWeightAMI<SourcePatch, TargetPatch>::processSourceFace
( (
const label srcFacei, const label srcFacei,
const label tgtStartFacei, const label tgtStartFacei,
@ -213,15 +188,11 @@ bool Foam::faceAreaWeightAMI<SourcePatch, TargetPatch>::processSourceFace
return false; return false;
} }
const auto& tgtPatch = this->tgtPatch();
// append initial target face and neighbours // append initial target face and neighbours
nbrFaces.append(tgtStartFacei); nbrFaces.append(tgtStartFacei);
this->appendNbrFaces appendNbrFaces(tgtStartFacei, tgtPatch, visitedFaces, nbrFaces);
(
tgtStartFacei,
this->tgtPatch(),
visitedFaces,
nbrFaces
);
bool faceProcessed = false; bool faceProcessed = false;
@ -238,11 +209,7 @@ bool Foam::faceAreaWeightAMI<SourcePatch, TargetPatch>::processSourceFace
calcInterArea(srcFacei, tgtFacei, interArea, interCentroid); calcInterArea(srcFacei, tgtFacei, interArea, interCentroid);
// store when intersection fractional area > tolerance // store when intersection fractional area > tolerance
if if (interArea/srcMagSf_[srcFacei] > faceAreaIntersect::tolerance())
(
interArea/this->srcMagSf_[srcFacei]
> faceAreaIntersect::tolerance()
)
{ {
srcAddr[srcFacei].append(tgtFacei); srcAddr[srcFacei].append(tgtFacei);
srcWght[srcFacei].append(interArea); srcWght[srcFacei].append(interArea);
@ -251,13 +218,7 @@ bool Foam::faceAreaWeightAMI<SourcePatch, TargetPatch>::processSourceFace
tgtAddr[tgtFacei].append(srcFacei); tgtAddr[tgtFacei].append(srcFacei);
tgtWght[tgtFacei].append(interArea); tgtWght[tgtFacei].append(interArea);
this->appendNbrFaces appendNbrFaces(tgtFacei, tgtPatch, visitedFaces, nbrFaces);
(
tgtFacei,
this->tgtPatch(),
visitedFaces,
nbrFaces
);
faceProcessed = true; faceProcessed = true;
@ -275,8 +236,7 @@ bool Foam::faceAreaWeightAMI<SourcePatch, TargetPatch>::processSourceFace
} }
template<class SourcePatch, class TargetPatch> bool Foam::faceAreaWeightAMI::setNextFaces
void Foam::faceAreaWeightAMI<SourcePatch, TargetPatch>::setNextFaces
( (
label& startSeedi, label& startSeedi,
label& srcFacei, label& srcFacei,
@ -289,12 +249,18 @@ void Foam::faceAreaWeightAMI<SourcePatch, TargetPatch>::setNextFaces
{ {
addProfiling(ami, "faceAreaWeightAMI::setNextFaces"); addProfiling(ami, "faceAreaWeightAMI::setNextFaces");
if (mapFlag.count() == 0)
{
// No more faces to map
return false;
}
const labelList& srcNbrFaces = this->srcPatch().faceFaces()[srcFacei]; const labelList& srcNbrFaces = this->srcPatch().faceFaces()[srcFacei];
// initialise tgtFacei // Initialise tgtFacei
tgtFacei = -1; tgtFacei = -1;
// set possible seeds for later use // Set possible seeds for later use
bool valuesSet = false; bool valuesSet = false;
for (label faceS: srcNbrFaces) for (label faceS: srcNbrFaces)
{ {
@ -303,7 +269,7 @@ void Foam::faceAreaWeightAMI<SourcePatch, TargetPatch>::setNextFaces
for (label faceT : visitedFaces) for (label faceT : visitedFaces)
{ {
const scalar threshold = const scalar threshold =
this->srcMagSf_[faceS]*faceAreaIntersect::tolerance(); srcMagSf_[faceS]*faceAreaIntersect::tolerance();
// Store when intersection fractional area > threshold // Store when intersection fractional area > threshold
if (overlaps(faceS, faceT, threshold)) if (overlaps(faceS, faceT, threshold))
@ -321,73 +287,73 @@ void Foam::faceAreaWeightAMI<SourcePatch, TargetPatch>::setNextFaces
} }
} }
// set next src and tgt faces if not set above
if (valuesSet) if (valuesSet)
{ {
return; return true;
} }
else
// Set next src and tgt faces if not set above
// - try to use existing seed
label facei = startSeedi;
if (!mapFlag.test(startSeedi))
{ {
// try to use existing seed facei = mapFlag.find_next(facei);
label facei = startSeedi; }
if (!mapFlag.test(startSeedi)) const label startSeedi0 = facei;
bool foundNextSeed = false;
while (facei != -1)
{
if (!foundNextSeed)
{ {
facei = mapFlag.find_next(facei); startSeedi = facei;
} foundNextSeed = true;
const label startSeedi0 = facei;
bool foundNextSeed = false;
while (facei != -1)
{
if (!foundNextSeed)
{
startSeedi = facei;
foundNextSeed = true;
}
if (seedFaces[facei] != -1)
{
srcFacei = facei;
tgtFacei = seedFaces[facei];
return;
}
facei = mapFlag.find_next(facei);
} }
// perform new search to find match if (seedFaces[facei] != -1)
if (debug)
{
Pout<< "Advancing front stalled: searching for new "
<< "target face" << endl;
}
facei = startSeedi0;
while (facei != -1)
{ {
srcFacei = facei; srcFacei = facei;
tgtFacei = this->findTargetFace(srcFacei, visitedFaces); tgtFacei = seedFaces[facei];
if (tgtFacei >= 0) return true;
{
return;
}
facei = mapFlag.find_next(facei);
} }
if (errorOnNotFound) facei = mapFlag.find_next(facei);
{
FatalErrorInFunction
<< "Unable to set source and target faces" << abort(FatalError);
}
} }
// Perform new search to find match
if (debug)
{
Pout<< "Advancing front stalled: searching for new "
<< "target face" << endl;
}
facei = startSeedi0;
while (facei != -1)
{
srcFacei = facei;
tgtFacei = findTargetFace(srcFacei, visitedFaces);
if (tgtFacei >= 0)
{
return true;
}
facei = mapFlag.find_next(facei);
}
if (errorOnNotFound)
{
FatalErrorInFunction
<< "Unable to set target face for source face " << srcFacei
<< abort(FatalError);
}
return false;
} }
template<class SourcePatch, class TargetPatch> void Foam::faceAreaWeightAMI::calcInterArea
void Foam::faceAreaWeightAMI<SourcePatch, TargetPatch>::calcInterArea
( (
const label srcFacei, const label srcFacei,
const label tgtFacei, const label tgtFacei,
@ -397,46 +363,48 @@ void Foam::faceAreaWeightAMI<SourcePatch, TargetPatch>::calcInterArea
{ {
addProfiling(ami, "faceAreaWeightAMI::interArea"); addProfiling(ami, "faceAreaWeightAMI::interArea");
const pointField& srcPoints = this->srcPatch().points(); // Quick reject if either face has zero area
const pointField& tgtPoints = this->tgtPatch().points();
// references to candidate faces
const face& src = this->srcPatch()[srcFacei];
const face& tgt = this->tgtPatch()[tgtFacei];
// quick reject if either face has zero area
if if
( (
(this->srcMagSf_[srcFacei] < ROOTVSMALL) (srcMagSf_[srcFacei] < ROOTVSMALL)
|| (this->tgtMagSf_[tgtFacei] < ROOTVSMALL) || (tgtMagSf_[tgtFacei] < ROOTVSMALL)
) )
{ {
return; return;
} }
// create intersection object const auto& srcPatch = this->srcPatch();
const auto& tgtPatch = this->tgtPatch();
const pointField& srcPoints = srcPatch.points();
const pointField& tgtPoints = tgtPatch.points();
// Create intersection object
faceAreaIntersect inter faceAreaIntersect inter
( (
srcPoints, srcPoints,
tgtPoints, tgtPoints,
this->srcTris_[srcFacei], srcTris_[srcFacei],
this->tgtTris_[tgtFacei], tgtTris_[tgtFacei],
this->reverseTarget_, reverseTarget_,
AMIInterpolation<SourcePatch, TargetPatch>::cacheIntersections_ AMIInterpolation::cacheIntersections_
); );
// crude resultant norm // Crude resultant norm
vector n(-this->srcPatch().faceNormals()[srcFacei]); vector n(-srcPatch.faceNormals()[srcFacei]);
if (this->reverseTarget_) if (reverseTarget_)
{ {
n -= this->tgtPatch().faceNormals()[tgtFacei]; n -= tgtPatch.faceNormals()[tgtFacei];
} }
else else
{ {
n += this->tgtPatch().faceNormals()[tgtFacei]; n += tgtPatch.faceNormals()[tgtFacei];
} }
scalar magN = mag(n); scalar magN = mag(n);
const face& src = srcPatch[srcFacei];
const face& tgt = tgtPatch[tgtFacei];
if (magN > ROOTVSMALL) if (magN > ROOTVSMALL)
{ {
inter.calc(src, tgt, n/magN, area, centroid); inter.calc(src, tgt, n/magN, area, centroid);
@ -451,11 +419,7 @@ void Foam::faceAreaWeightAMI<SourcePatch, TargetPatch>::calcInterArea
<< endl; << endl;
} }
if if (AMIInterpolation::cacheIntersections_ && debug)
(
AMIInterpolation<SourcePatch, TargetPatch>::cacheIntersections_
&& debug
)
{ {
static OBJstream tris("intersectionTris.obj"); static OBJstream tris("intersectionTris.obj");
const auto& triPts = inter.triangles(); const auto& triPts = inter.triangles();
@ -467,58 +431,59 @@ void Foam::faceAreaWeightAMI<SourcePatch, TargetPatch>::calcInterArea
if ((debug > 1) && (area > 0)) if ((debug > 1) && (area > 0))
{ {
this->writeIntersectionOBJ(area, src, tgt, srcPoints, tgtPoints); writeIntersectionOBJ(area, src, tgt, srcPoints, tgtPoints);
} }
} }
template<class SourcePatch, class TargetPatch> bool Foam::faceAreaWeightAMI::overlaps
bool Foam::faceAreaWeightAMI<SourcePatch, TargetPatch>::overlaps
( (
const label srcFacei, const label srcFacei,
const label tgtFacei, const label tgtFacei,
const scalar threshold const scalar threshold
) const ) const
{ {
const pointField& srcPoints = this->srcPatch().points(); // Quick reject if either face has zero area
const pointField& tgtPoints = this->tgtPatch().points();
// references to candidate faces
const face& src = this->srcPatch()[srcFacei];
const face& tgt = this->tgtPatch()[tgtFacei];
// quick reject if either face has zero area
if if
( (
(this->srcMagSf_[srcFacei] < ROOTVSMALL) (srcMagSf_[srcFacei] < ROOTVSMALL)
|| (this->tgtMagSf_[tgtFacei] < ROOTVSMALL) || (tgtMagSf_[tgtFacei] < ROOTVSMALL)
) )
{ {
return false; return false;
} }
const auto& srcPatch = this->srcPatch();
const auto& tgtPatch = this->tgtPatch();
const pointField& srcPoints = srcPatch.points();
const pointField& tgtPoints = tgtPatch.points();
faceAreaIntersect inter faceAreaIntersect inter
( (
srcPoints, srcPoints,
tgtPoints, tgtPoints,
this->srcTris_[srcFacei], srcTris_[srcFacei],
this->tgtTris_[tgtFacei], tgtTris_[tgtFacei],
this->reverseTarget_, reverseTarget_,
AMIInterpolation<SourcePatch, TargetPatch>::cacheIntersections_ AMIInterpolation::cacheIntersections_
); );
// crude resultant norm // Crude resultant norm
vector n(-this->srcPatch().faceNormals()[srcFacei]); vector n(-srcPatch.faceNormals()[srcFacei]);
if (this->reverseTarget_) if (reverseTarget_)
{ {
n -= this->tgtPatch().faceNormals()[tgtFacei]; n -= tgtPatch.faceNormals()[tgtFacei];
} }
else else
{ {
n += this->tgtPatch().faceNormals()[tgtFacei]; n += tgtPatch.faceNormals()[tgtFacei];
} }
scalar magN = mag(n); scalar magN = mag(n);
const face& src = srcPatch[srcFacei];
const face& tgt = tgtPatch[tgtFacei];
if (magN > ROOTVSMALL) if (magN > ROOTVSMALL)
{ {
return inter.overlaps(src, tgt, n/magN, threshold); return inter.overlaps(src, tgt, n/magN, threshold);
@ -537,9 +502,7 @@ bool Foam::faceAreaWeightAMI<SourcePatch, TargetPatch>::overlaps
} }
template<class SourcePatch, class TargetPatch> void Foam::faceAreaWeightAMI::restartUncoveredSourceFace
void Foam::faceAreaWeightAMI<SourcePatch, TargetPatch>::
restartUncoveredSourceFace
( (
List<DynamicList<label>>& srcAddr, List<DynamicList<label>>& srcAddr,
List<DynamicList<scalar>>& srcWght, List<DynamicList<scalar>>& srcWght,
@ -555,27 +518,29 @@ restartUncoveredSourceFace
label nBelowMinWeight = 0; label nBelowMinWeight = 0;
const scalar minWeight = 0.95; const scalar minWeight = 0.95;
// list of tgt face neighbour faces // List of tgt face neighbour faces
DynamicList<label> nbrFaces(10); DynamicList<label> nbrFaces(10);
// list of faces currently visited for srcFacei to avoid multiple hits // List of faces currently visited for srcFacei to avoid multiple hits
DynamicList<label> visitedFaces(10); DynamicList<label> visitedFaces(10);
const auto& srcPatch = this->srcPatch();
forAll(srcWght, srcFacei) forAll(srcWght, srcFacei)
{ {
const scalar s = sum(srcWght[srcFacei]); const scalar s = sum(srcWght[srcFacei]);
const scalar t = s/this->srcMagSf_[srcFacei]; const scalar t = s/srcMagSf_[srcFacei];
if (t < minWeight) if (t < minWeight)
{ {
++nBelowMinWeight; ++nBelowMinWeight;
const face& f = this->srcPatch()[srcFacei]; const face& f = srcPatch[srcFacei];
forAll(f, fpi) forAll(f, fpi)
{ {
const label tgtFacei = const label tgtFacei =
this->findTargetFace(srcFacei, srcAddr[srcFacei], fpi); findTargetFace(srcFacei, srcAddr[srcFacei], fpi);
if (tgtFacei != -1) if (tgtFacei != -1)
{ {
@ -613,77 +578,74 @@ restartUncoveredSourceFace
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
template<class SourcePatch, class TargetPatch> Foam::faceAreaWeightAMI::faceAreaWeightAMI
Foam::faceAreaWeightAMI<SourcePatch, TargetPatch>::faceAreaWeightAMI (
const dictionary& dict,
const bool reverseTarget
)
:
advancingFrontAMI(dict, reverseTarget),
restartUncoveredSourceFace_
(
dict.getOrDefault("restartUncoveredSourceFace", true)
)
{}
Foam::faceAreaWeightAMI::faceAreaWeightAMI
( (
const SourcePatch& srcPatch,
const TargetPatch& tgtPatch,
const faceAreaIntersect::triangulationMode& triMode,
const bool reverseTarget,
const bool requireMatch, const bool requireMatch,
const bool reverseTarget,
const scalar lowWeightCorrection,
const faceAreaIntersect::triangulationMode triMode,
const bool restartUncoveredSourceFace const bool restartUncoveredSourceFace
) )
: :
AMIMethod<SourcePatch, TargetPatch> advancingFrontAMI
( (
srcPatch, requireMatch,
tgtPatch,
triMode,
reverseTarget, reverseTarget,
requireMatch lowWeightCorrection,
triMode
), ),
restartUncoveredSourceFace_(restartUncoveredSourceFace), restartUncoveredSourceFace_(restartUncoveredSourceFace)
srcMagSf_(), {}
tgtMagSf_(),
srcTris_(),
tgtTris_(), Foam::faceAreaWeightAMI::faceAreaWeightAMI(const faceAreaWeightAMI& ami)
extendedTgtMapPtr_(nullptr) :
advancingFrontAMI(ami),
restartUncoveredSourceFace_(ami.restartUncoveredSourceFace_)
{} {}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class SourcePatch, class TargetPatch> bool Foam::faceAreaWeightAMI::calculate
bool Foam::faceAreaWeightAMI<SourcePatch, TargetPatch>::calculate
( (
labelListList& srcAddress, const primitivePatch& srcPatch,
scalarListList& srcWeights, const primitivePatch& tgtPatch,
pointListList& srcCentroids, const autoPtr<searchableSurface>& surfPtr
labelListList& tgtAddress,
scalarListList& tgtWeights,
scalarList& srcMagSf,
scalarList& tgtMagSf,
autoPtr<mapDistribute>& srcMapPtr,
autoPtr<mapDistribute>& tgtMapPtr,
label srcFacei,
label tgtFacei
) )
{ {
if (upToDate_)
{
return false;
}
addProfiling(ami, "faceAreaWeightAMI::calculate"); addProfiling(ami, "faceAreaWeightAMI::calculate");
// Create global indexing for each patch advancingFrontAMI::calculate(srcPatch, tgtPatch, surfPtr);
globalIndex globalSrcFaces(this->srcPatch0_.size());
globalIndex globalTgtFaces(this->tgtPatch0_.size());
// Initialise the geometry label srcFacei = 0;
labelList extendedTgtFaceIDs; label tgtFacei = 0;
initGeom(globalTgtFaces, extendedTgtFaceIDs);
bool ok = bool ok = initialiseWalk(srcFacei, tgtFacei);
this->initialise
(
srcAddress,
srcWeights,
tgtAddress,
tgtWeights,
srcFacei,
tgtFacei
);
srcCentroids.setSize(srcAddress.size()); srcCentroids_.setSize(srcAddress_.size());
const auto& src = this->srcPatch(); const auto& src = this->srcPatch();
const auto& tgt = this->tgtPatch(); const auto& tgt = this->tgtPatch(); // might be the extended patch!
// Temporary storage for addressing and weights // Temporary storage for addressing and weights
List<DynamicList<label>> srcAddr(src.size()); List<DynamicList<label>> srcAddr(src.size());
@ -705,15 +667,15 @@ bool Foam::faceAreaWeightAMI<SourcePatch, TargetPatch>::calculate
tgtFacei tgtFacei
); );
if (debug && !this->srcNonOverlap_.empty()) if (debug && !srcNonOverlap_.empty())
{ {
Pout<< " AMI: " << this->srcNonOverlap_.size() Pout<< " AMI: " << srcNonOverlap_.size()
<< " non-overlap faces identified" << " non-overlap faces identified"
<< endl; << endl;
} }
// Check for badly covered faces // Check for badly covered faces
if (restartUncoveredSourceFace_) if (restartUncoveredSourceFace_) // && requireMatch_???
{ {
restartUncoveredSourceFace restartUncoveredSourceFace
( (
@ -726,36 +688,38 @@ bool Foam::faceAreaWeightAMI<SourcePatch, TargetPatch>::calculate
} }
} }
// Set the patch face areas
srcMagSf = std::move(srcMagSf_);
tgtMagSf = std::move(tgtMagSf_);
// Transfer data to persistent storage // Transfer data to persistent storage
forAll(srcAddr, i) forAll(srcAddr, i)
{ {
srcAddress[i].transfer(srcAddr[i]); srcAddress_[i].transfer(srcAddr[i]);
srcWeights[i].transfer(srcWght[i]); srcWeights_[i].transfer(srcWght[i]);
srcCentroids[i].transfer(srcCtr[i]); srcCentroids_[i].transfer(srcCtr[i]);
} }
forAll(tgtAddr, i) forAll(tgtAddr, i)
{ {
tgtAddress[i].transfer(tgtAddr[i]); tgtAddress_[i].transfer(tgtAddr[i]);
tgtWeights[i].transfer(tgtWght[i]); tgtWeights_[i].transfer(tgtWght[i]);
} }
if (this->distributed()) if (distributed())
{ {
for (labelList& addressing : srcAddress) const primitivePatch& srcPatch0 = this->srcPatch0();
const primitivePatch& tgtPatch0 = this->tgtPatch0();
// Create global indexing for each original patch
globalIndex globalSrcFaces(srcPatch0.size());
globalIndex globalTgtFaces(tgtPatch0.size());
for (labelList& addressing : srcAddress_)
{ {
for (label& addr : addressing) for (label& addr : addressing)
{ {
addr = extendedTgtFaceIDs[addr]; addr = extendedTgtFaceIDs_[addr];
} }
} }
for (labelList& addressing : tgtAddress) for (labelList& addressing : tgtAddress_)
{ {
globalSrcFaces.inplaceToGlobal(addressing); globalSrcFaces.inplaceToGlobal(addressing);
} }
@ -767,12 +731,12 @@ bool Foam::faceAreaWeightAMI<SourcePatch, TargetPatch>::calculate
( (
Pstream::commsTypes::nonBlocking, Pstream::commsTypes::nonBlocking,
List<labelPair>(), List<labelPair>(),
this->tgtPatch0_.size(), tgtPatch0.size(),
extendedTgtMapPtr_->constructMap(), extendedTgtMapPtr_->constructMap(),
false, // has flip false, // has flip
extendedTgtMapPtr_->subMap(), extendedTgtMapPtr_->subMap(),
false, // has flip false, // has flip
tgtAddress, tgtAddress_,
ListOps::appendEqOp<label>(), ListOps::appendEqOp<label>(),
flipOp(), // flip operation flipOp(), // flip operation
labelList() labelList()
@ -782,43 +746,55 @@ bool Foam::faceAreaWeightAMI<SourcePatch, TargetPatch>::calculate
( (
Pstream::commsTypes::nonBlocking, Pstream::commsTypes::nonBlocking,
List<labelPair>(), List<labelPair>(),
this->tgtPatch0_.size(), tgtPatch0.size(),
extendedTgtMapPtr_->constructMap(), extendedTgtMapPtr_->constructMap(),
false, false,
extendedTgtMapPtr_->subMap(), extendedTgtMapPtr_->subMap(),
false, false,
tgtWeights, tgtWeights_,
ListOps::appendEqOp<scalar>(), ListOps::appendEqOp<scalar>(),
flipOp(), flipOp(),
scalarList() scalarList()
); );
// Note: using patch face areas calculated by the AMI method // Note: using patch face areas calculated by the AMI method
extendedTgtMapPtr_->reverseDistribute extendedTgtMapPtr_->reverseDistribute(tgtPatch0.size(), tgtMagSf_);
(
this->tgtPatch0_.size(),
tgtMagSf
);
// Cache maps and reset addresses // Cache maps and reset addresses
List<Map<label>> cMapSrc; List<Map<label>> cMapSrc;
srcMapPtr.reset(new mapDistribute(globalSrcFaces, tgtAddress, cMapSrc)); srcMapPtr_.reset
(
new mapDistribute(globalSrcFaces, tgtAddress_, cMapSrc)
);
List<Map<label>> cMapTgt; List<Map<label>> cMapTgt;
tgtMapPtr.reset(new mapDistribute(globalTgtFaces, srcAddress, cMapTgt)); tgtMapPtr_.reset
(
new mapDistribute(globalTgtFaces, srcAddress_, cMapTgt)
);
} }
return true; // Convert the weights from areas to normalised values
normaliseWeights(conformal(), true);
upToDate_ = true;
return upToDate_;
} }
template<class SourcePatch, class TargetPatch> void Foam::faceAreaWeightAMI::write(Ostream& os) const
void Foam::faceAreaWeightAMI<SourcePatch, TargetPatch>::normaliseWeights
(
const bool verbose,
AMIInterpolation<SourcePatch, TargetPatch>& inter
)
{ {
inter.normaliseWeights(this->conformal(), verbose); advancingFrontAMI::write(os);
if (restartUncoveredSourceFace_)
{
os.writeEntry
(
"restartUncoveredSourceFace",
restartUncoveredSourceFace_
);
}
} }

View File

@ -38,7 +38,7 @@ SourceFiles
#ifndef faceAreaWeightAMI_H #ifndef faceAreaWeightAMI_H
#define faceAreaWeightAMI_H #define faceAreaWeightAMI_H
#include "AMIMethod.H" #include "advancingFrontAMI.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -49,10 +49,9 @@ namespace Foam
Class faceAreaWeightAMI Declaration Class faceAreaWeightAMI Declaration
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
template<class SourcePatch, class TargetPatch>
class faceAreaWeightAMI class faceAreaWeightAMI
: :
public AMIMethod<SourcePatch, TargetPatch> public advancingFrontAMI
{ {
private: private:
@ -61,35 +60,20 @@ private:
//- Flag to restart uncovered source faces //- Flag to restart uncovered source faces
const bool restartUncoveredSourceFace_; const bool restartUncoveredSourceFace_;
//- Source face areas
List<scalar> srcMagSf_;
//- Target face areas
List<scalar> tgtMagSf_;
//- Storage for src-side triangle decomposition
List<DynamicList<face>> srcTris_;
//- Storage for tgt-side triangle decomposition
List<DynamicList<face>> tgtTris_;
protected: protected:
autoPtr<mapDistribute> extendedTgtMapPtr_;
// Protected Member Functions // Protected Member Functions
//- No copy construct
faceAreaWeightAMI(const faceAreaWeightAMI&) = delete;
//- No copy assignment //- No copy assignment
void operator=(const faceAreaWeightAMI&) = delete; void operator=(const faceAreaWeightAMI&) = delete;
//- Initialise the geometry //- Initialise the geometry
void initGeom void initGeom
( (
const primitivePatch& srcPatch,
const primitivePatch& tgtPatch,
const globalIndex& globalTgtFaces, const globalIndex& globalTgtFaces,
labelList& extendedTgtFaceIDs labelList& extendedTgtFaceIDs
); );
@ -135,7 +119,7 @@ protected:
); );
//- Set the source and target seed faces //- Set the source and target seed faces
virtual void setNextFaces virtual bool setNextFaces
( (
label& startSeedi, label& startSeedi,
label& srcFacei, label& srcFacei,
@ -175,17 +159,33 @@ public:
// Constructors // Constructors
//- Construct from dictionary
faceAreaWeightAMI
(
const dictionary& dict,
const bool reverseTarget = false
);
//- Construct from components //- Construct from components
faceAreaWeightAMI faceAreaWeightAMI
( (
const SourcePatch& srcPatch, const bool requireMatch,
const TargetPatch& tgtPatch,
const faceAreaIntersect::triangulationMode& triMode,
const bool reverseTarget = false, const bool reverseTarget = false,
const bool requireMatch = true, const scalar lowWeightCorrection = -1,
const faceAreaIntersect::triangulationMode triMode =
faceAreaIntersect::tmMesh,
const bool restartUncoveredSourceFace = true const bool restartUncoveredSourceFace = true
); );
//- Construct as copy
faceAreaWeightAMI(const faceAreaWeightAMI& ami);
//- Construct and return a clone
virtual autoPtr<AMIInterpolation> clone() const
{
return autoPtr<AMIInterpolation>(new faceAreaWeightAMI(*this));
}
//- Destructor //- Destructor
virtual ~faceAreaWeightAMI() = default; virtual ~faceAreaWeightAMI() = default;
@ -193,31 +193,16 @@ public:
// Member Functions // Member Functions
// Manipulation //- Update addressing, weights and (optional) centroids
virtual bool calculate
(
const primitivePatch& srcPatch,
const primitivePatch& tgtPatch,
const autoPtr<searchableSurface>& surfPtr = nullptr
);
//- Update addressing, weights and centroids //- Write
virtual bool calculate virtual void write(Ostream& os) const;
(
labelListList& srcAddress,
scalarListList& srcWeights,
pointListList& srcCentroids,
labelListList& tgtAddress,
scalarListList& tgtWeights,
scalarList& srcMagSf,
scalarList& tgtMagSf,
autoPtr<mapDistribute>& srcMapPtr,
autoPtr<mapDistribute>& tgtMapPtr,
label srcFacei = -1,
label tgtFacei = -1
);
//- Normalise the weight. Can optionally subset addressing
//- (e.g. for mapNearest)
virtual void normaliseWeights
(
const bool verbose,
AMIInterpolation<SourcePatch, TargetPatch>& inter
);
}; };
@ -227,12 +212,6 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "faceAreaWeightAMI.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif #endif
// ************************************************************************* // // ************************************************************************* //

View File

@ -0,0 +1,408 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "nearestFaceAMI.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(nearestFaceAMI, 0);
addToRunTimeSelectionTable(AMIInterpolation, nearestFaceAMI, dict);
addToRunTimeSelectionTable(AMIInterpolation, nearestFaceAMI, component);
}
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
Foam::autoPtr<Foam::mapDistribute> Foam::nearestFaceAMI::calcFaceMap
(
const List<nearestAndDist>& localInfo,
const primitivePatch& srcPatch,
const primitivePatch& tgtPatch
) const
{
// Generate the list of processor bounding boxes for tgtPatch
List<boundBox> procBbs(Pstream::nProcs());
procBbs[Pstream::myProcNo()] =
boundBox(tgtPatch.points(), tgtPatch.meshPoints(), true);
Pstream::gatherList(procBbs);
Pstream::scatterList(procBbs);
// Identify which of my local src faces intersect with each processor
// tgtPatch bb within the current match's search distance
const pointField& srcCcs = srcPatch.faceCentres();
List<DynamicList<label>> dynSendMap(Pstream::nProcs());
forAll(localInfo, srcFacei)
{
// Test local srcPatch face centres against remote processor tgtPatch bb
// using distance from initial pass
const scalar r2 = localInfo[srcFacei].second();
forAll(procBbs, proci)
{
if (proci != Pstream::myProcNo())
{
if (procBbs[proci].overlaps(srcCcs[srcFacei], r2))
{
dynSendMap[proci].append(srcFacei);
}
}
}
}
// Convert dynamicList to labelList
labelListList sendMap(Pstream::nProcs());
forAll(sendMap, proci)
{
dynSendMap[proci].shrink();
sendMap[proci].transfer(dynSendMap[proci]);
if (debug)
{
Pout<< "send map - to proc " << proci << " sending "
<< sendMap[proci].size() << " elements" << endl;
}
}
return autoPtr<mapDistribute>::New(std::move(sendMap));
}
Foam::autoPtr<Foam::mapDistribute> Foam::nearestFaceAMI::calcDistributed
(
const primitivePatch& src,
const primitivePatch& tgt,
labelListList& srcToTgtAddr,
scalarListList& srcToTgtWght
) const
{
autoPtr<indexedOctree<treeType>> tgtTreePtr;
if (tgt.size())
{
tgtTreePtr = this->createTree(tgt);
}
// Create global indexing for tgtPatch
globalIndex globalTgtCells(tgt.size());
// First pass
// ==========
// For each srcPatch face, determine local match on tgtPatch
// Identify local nearest matches
pointField srcCcs(src.faceCentres());
List<nearestAndDist> localInfo(src.size());
if (tgt.size())
{
const auto& tgtTree = tgtTreePtr();
forAll(srcCcs, srcCelli)
{
const point& srcCc = srcCcs[srcCelli];
pointIndexHit& test = localInfo[srcCelli].first();
test = tgtTree.findNearest(srcCc, GREAT);
if (test.hit())
{
// With a search radius2 of GREAT all cells should receive a hit
localInfo[srcCelli].second() = magSqr(srcCc - test.hitPoint());
test.setIndex(globalTgtCells.toGlobal(test.index()));
}
}
}
else
{
// No local tgtPatch faces - initialise nearest distance for all
// srcPatch faces to GREAT so that they [should be] set by remote
// tgtPatch faces
for (auto& info : localInfo)
{
info.second() = GREAT;
}
}
// Second pass
// ===========
// Determine remote matches
// Map returns labels of src patch faces to send to each proc
autoPtr<mapDistribute> mapPtr = calcFaceMap(localInfo, src, tgt);
mapDistribute& map = mapPtr();
List<nearestAndDist> remoteInfo(localInfo);
map.distribute(remoteInfo);
// Note: re-using srcCcs
map.distribute(srcCcs);
if (tgt.size())
{
const auto& tgtTree = tgtTreePtr();
// Test remote srcPatch faces against local tgtPatch faces
nearestAndDist testInfo;
pointIndexHit& test = testInfo.first();
forAll(remoteInfo, i)
{
test = tgtTree.findNearest(srcCcs[i], remoteInfo[i].second());
if (test.hit())
{
test.setIndex(globalTgtCells.toGlobal(test.index()));
testInfo.second() = magSqr(test.hitPoint() - srcCcs[i]);
nearestEqOp()(remoteInfo[i], testInfo);
}
}
}
// Send back to originating processor. Choose best if sent to multiple
// processors. Note that afterwards all unused entries have the unique
// value nearestZero (distance < 0). This is used later on to see if
// the sample was sent to any processor.
const nearestAndDist nearestZero(pointIndexHit(), -GREAT);
mapDistributeBase::distribute
(
Pstream::commsTypes::nonBlocking,
List<labelPair>(0),
src.size(),
map.constructMap(),
map.constructHasFlip(),
map.subMap(),
map.subHasFlip(),
remoteInfo,
nearestEqOp(),
noOp(), // no flipping
nearestZero
);
// Third pass
// ==========
// Combine local and remote info and filter out any connections that are
// further away than threshold distance squared
srcToTgtAddr.setSize(src.size());
srcToTgtWght.setSize(src.size());
forAll(srcToTgtAddr, srcFacei)
{
nearestEqOp()(localInfo[srcFacei], remoteInfo[srcFacei]);
if (localInfo[srcFacei].second() < maxDistance2_)
{
const label tgtFacei = localInfo[srcFacei].first().index();
srcToTgtAddr[srcFacei] = labelList(1, tgtFacei);
srcToTgtWght[srcFacei] = scalarList(1, 1.0);
}
}
List<Map<label>> cMap;
return autoPtr<mapDistribute>::New(globalTgtCells, srcToTgtAddr, cMap);
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::nearestFaceAMI::nearestFaceAMI
(
const dictionary& dict,
const bool reverseTarget
)
:
AMIInterpolation(dict, reverseTarget),
maxDistance2_(dict.getOrDefault<scalar>("maxDistance2", GREAT))
{}
Foam::nearestFaceAMI::nearestFaceAMI
(
const bool requireMatch,
const bool reverseTarget,
const scalar lowWeightCorrection
)
:
AMIInterpolation(requireMatch, reverseTarget, lowWeightCorrection),
maxDistance2_(GREAT)
{}
Foam::nearestFaceAMI::nearestFaceAMI(const nearestFaceAMI& ami)
:
AMIInterpolation(ami),
maxDistance2_(ami.maxDistance2_)
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
bool Foam::nearestFaceAMI::calculate
(
const primitivePatch& srcPatch,
const primitivePatch& tgtPatch,
const autoPtr<searchableSurface>& surfPtr
)
{
if (upToDate_)
{
return false;
}
AMIInterpolation::calculate(srcPatch, tgtPatch, surfPtr);
const auto& src = this->srcPatch0();
const auto& tgt = this->tgtPatch0();
// Set face area magnitudes
srcMagSf_ = mag(src.faceAreas());
tgtMagSf_ = mag(tgt.faceAreas());
// TODO: implement symmetric calculation controls; assume yes for now
bool symmetric_ = true;
if (this->distributed())
{
tgtMapPtr_ =
calcDistributed
(
src,
tgt,
srcAddress_,
srcWeights_
);
if (symmetric_)
{
srcMapPtr_ =
calcDistributed
(
tgt,
src,
tgtAddress_,
tgtWeights_
);
}
}
else
{
srcAddress_.setSize(src.size());
srcWeights_.setSize(src.size());
if (symmetric_)
{
tgtAddress_.setSize(tgt.size());
tgtWeights_.setSize(tgt.size());
}
const pointField& srcCcs = src.faceCentres();
const pointField& tgtCcs = tgt.faceCentres();
const auto tgtTreePtr = this->createTree(tgtPatch);
const auto& tgtTree = tgtTreePtr();
forAll(srcCcs, srcFacei)
{
const point& srcCc = srcCcs[srcFacei];
const pointIndexHit hit = tgtTree.findNearest(srcCc, GREAT);
if
(
hit.hit()
&& (magSqr(srcCc - tgtCcs[hit.index()]) < maxDistance2_)
)
{
label tgtFacei = hit.index();
srcAddress_[srcFacei] = labelList(1, tgtFacei);
srcWeights_[srcFacei] = scalarList(1, 1.0);
if (symmetric_)
{
tgtAddress_[tgtFacei] = labelList(1, srcFacei);
tgtWeights_[tgtFacei] = scalarList(1, 1.0);
}
}
else
{
if (debug)
{
WarningInFunction
<< "Unable to find target face for source face "
<< srcFacei << endl;
}
}
}
if (symmetric_)
{
const auto srcTreePtr = this->createTree(srcPatch);
const auto& srcTree = srcTreePtr();
// Check that all source cells have connections and populate any
// missing entries
forAll(tgtWeights_, tgtCelli)
{
if (tgtAddress_[tgtCelli].empty())
{
const point& tgtCc = tgtCcs[tgtCelli];
pointIndexHit hit = srcTree.findNearest(tgtCc, GREAT);
if
(
hit.hit()
&& (magSqr(tgtCc - srcCcs[hit.index()]) < maxDistance2_)
)
{
tgtAddress_[tgtCelli] = labelList(1, hit.index());
tgtWeights_[tgtCelli] = scalarList(1, 1.0);
}
}
else
{
if (debug)
{
WarningInFunction
<< "Unable to find source face for target face "
<< tgtCelli << endl;
}
}
}
}
}
srcWeightsSum_.setSize(srcWeights_.size(), 1);
tgtWeightsSum_.setSize(tgtWeights_.size(), 1);
upToDate_ = true;
return upToDate_;
}
// ************************************************************************* //

View File

@ -37,7 +37,7 @@ SourceFiles
#ifndef nearestFaceAMI_H #ifndef nearestFaceAMI_H
#define nearestFaceAMI_H #define nearestFaceAMI_H
#include "AMIMethod.H" #include "AMIInterpolation.H"
#include "pointIndexHit.H" #include "pointIndexHit.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -49,10 +49,9 @@ namespace Foam
Class nearestFaceAMI Declaration Class nearestFaceAMI Declaration
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
template<class SourcePatch, class TargetPatch>
class nearestFaceAMI class nearestFaceAMI
: :
public AMIMethod<SourcePatch, TargetPatch> public AMIInterpolation
{ {
public: public:
@ -91,23 +90,20 @@ private:
// Private Member Functions // Private Member Functions
//- No copy construct
nearestFaceAMI(const nearestFaceAMI&) = delete;
//- No copy assignment //- No copy assignment
void operator=(const nearestFaceAMI&) = delete; void operator=(const nearestFaceAMI&) = delete;
autoPtr<mapDistribute> calcFaceMap autoPtr<mapDistribute> calcFaceMap
( (
const List<nearestAndDist>& localInfo, const List<nearestAndDist>& localInfo,
const SourcePatch& srcPatch, const primitivePatch& srcPatch,
const TargetPatch& tgtPatch const primitivePatch& tgtPatch
) const; ) const;
autoPtr<mapDistribute> calcDistributed autoPtr<mapDistribute> calcDistributed
( (
const SourcePatch& src, const primitivePatch& src,
const TargetPatch& tgt, const primitivePatch& tgt,
labelListList& srcToTgtAddr, labelListList& srcToTgtAddr,
scalarListList& srcToTgtWght scalarListList& srcToTgtWght
) const; ) const;
@ -121,16 +117,30 @@ public:
// Constructors // Constructors
//- Construct from dictionary
nearestFaceAMI
(
const dictionary& dict,
const bool reverseTarget = false
);
//- Construct from components //- Construct from components
nearestFaceAMI nearestFaceAMI
( (
const SourcePatch& srcPatch, const bool requireMatch = true,
const TargetPatch& tgtPatch,
const faceAreaIntersect::triangulationMode& triMode,
const bool reverseTarget = false, const bool reverseTarget = false,
const bool requireMatch = true const scalar lowWeightCorrection = -1
); );
//- Construct as copy
nearestFaceAMI(const nearestFaceAMI& ami);
//- Construct and return a clone
virtual autoPtr<AMIInterpolation> clone() const
{
return autoPtr<AMIInterpolation>(new nearestFaceAMI(*this));
}
//- Destructor //- Destructor
virtual ~nearestFaceAMI() = default; virtual ~nearestFaceAMI() = default;
@ -138,31 +148,13 @@ public:
// Member Functions // Member Functions
// Manipulation //- Update addressing and weights
virtual bool calculate
//- Update addressing and weights (
virtual bool calculate const primitivePatch& srcPatch,
( const primitivePatch& tgtPatch,
labelListList& srcAddress, const autoPtr<searchableSurface>& surfPtr = nullptr
scalarListList& srcWeights, );
pointListList& srcCentroids,
labelListList& tgtAddress,
scalarListList& tgtWeights,
scalarList& srcMagSf,
scalarList& tgtMagSf,
autoPtr<mapDistribute>& srcMapPtr,
autoPtr<mapDistribute>& tgtMapPtr,
label srcFacei = -1,
label tgtFacei = -1
);
//- Normalise the weight. Can optionally subset addressing
//- (e.g. for mapNearest)
virtual void normaliseWeights
(
const bool verbose,
AMIInterpolation<SourcePatch, TargetPatch>& inter
);
}; };
@ -172,12 +164,6 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "nearestFaceAMI.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif #endif
// ************************************************************************* // // ************************************************************************* //

View File

@ -6,6 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2013-2016 OpenFOAM Foundation Copyright (C) 2013-2016 OpenFOAM Foundation
Copyright (C) 2020 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -26,11 +27,30 @@ License
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#include "partialFaceAreaWeightAMI.H" #include "partialFaceAreaWeightAMI.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(partialFaceAreaWeightAMI, 0);
addToRunTimeSelectionTable
(
AMIInterpolation,
partialFaceAreaWeightAMI,
dict
);
addToRunTimeSelectionTable
(
AMIInterpolation,
partialFaceAreaWeightAMI,
component
);
}
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
template<class SourcePatch, class TargetPatch> bool Foam::partialFaceAreaWeightAMI::setNextFaces
void Foam::partialFaceAreaWeightAMI<SourcePatch, TargetPatch>::setNextFaces
( (
label& startSeedi, label& startSeedi,
label& srcFacei, label& srcFacei,
@ -41,7 +61,7 @@ void Foam::partialFaceAreaWeightAMI<SourcePatch, TargetPatch>::setNextFaces
const bool errorOnNotFound const bool errorOnNotFound
) const ) const
{ {
faceAreaWeightAMI<SourcePatch, TargetPatch>::setNextFaces return faceAreaWeightAMI::setNextFaces
( (
startSeedi, startSeedi,
srcFacei, srcFacei,
@ -56,85 +76,75 @@ void Foam::partialFaceAreaWeightAMI<SourcePatch, TargetPatch>::setNextFaces
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
template<class SourcePatch, class TargetPatch> Foam::partialFaceAreaWeightAMI::partialFaceAreaWeightAMI
Foam::partialFaceAreaWeightAMI<SourcePatch, TargetPatch>::
partialFaceAreaWeightAMI
( (
const SourcePatch& srcPatch, const dictionary& dict,
const TargetPatch& tgtPatch, const bool reverseTarget
const faceAreaIntersect::triangulationMode& triMode,
const bool reverseTarget,
const bool requireMatch
) )
: :
faceAreaWeightAMI<SourcePatch, TargetPatch> faceAreaWeightAMI(dict, reverseTarget)
{}
Foam::partialFaceAreaWeightAMI::partialFaceAreaWeightAMI
(
const bool requireMatch,
const bool reverseTarget,
const scalar lowWeightCorrection,
const faceAreaIntersect::triangulationMode triMode,
const bool restartUncoveredSourceFace
)
:
faceAreaWeightAMI
( (
srcPatch,
tgtPatch,
triMode,
reverseTarget,
requireMatch, requireMatch,
true // false // Not performing restart on low weights - valid for partial match reverseTarget,
lowWeightCorrection,
triMode,
restartUncoveredSourceFace
) )
{} {}
Foam::partialFaceAreaWeightAMI::partialFaceAreaWeightAMI
(
const partialFaceAreaWeightAMI& ami
)
:
faceAreaWeightAMI(ami)
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class SourcePatch, class TargetPatch> bool Foam::partialFaceAreaWeightAMI::conformal() const
bool Foam::partialFaceAreaWeightAMI<SourcePatch, TargetPatch>::conformal() const
{ {
return false; return false;
} }
template<class SourcePatch, class TargetPatch> bool Foam::partialFaceAreaWeightAMI::calculate
bool Foam::partialFaceAreaWeightAMI<SourcePatch, TargetPatch>::calculate
( (
labelListList& srcAddress, const primitivePatch& srcPatch,
scalarListList& srcWeights, const primitivePatch& tgtPatch,
pointListList& srcCentroids, const autoPtr<searchableSurface>& surfPtr
labelListList& tgtAddress,
scalarListList& tgtWeights,
scalarList& srcMagSf,
scalarList& tgtMagSf,
autoPtr<mapDistribute>& srcMapPtr,
autoPtr<mapDistribute>& tgtMapPtr,
label srcFacei,
label tgtFacei
) )
{ {
bool ok = if (faceAreaWeightAMI::calculate(srcPatch, tgtPatch, surfPtr))
faceAreaWeightAMI<SourcePatch, TargetPatch>::calculate
(
srcAddress,
srcWeights,
srcCentroids,
tgtAddress,
tgtWeights,
srcMagSf,
tgtMagSf,
srcMapPtr,
tgtMapPtr,
srcFacei,
tgtFacei
);
if (ok)
{ {
if (this->distributed()) if (distributed())
{ {
scalarList newTgtMagSf(std::move(tgtMagSf)); scalarList newTgtMagSf(std::move(tgtMagSf_));
// Assign default sizes. Override selected values with // Assign default sizes. Override selected values with calculated
// calculated values. This is to support ACMI // values. This is to support ACMI where some of the target faces
// where some of the target faces are never used (so never get sent // are never used (so never get sent over and hence never assigned
// over and hence never assigned to) // to)
tgtMagSf = this->tgtPatch0_.magFaceAreas(); tgtMagSf_ = tgtPatch0().magFaceAreas();
for (const labelList& smap : this->extendedTgtMapPtr_->subMap()) for (const labelList& smap : this->extendedTgtMapPtr_->subMap())
{ {
UIndirectList<scalar>(tgtMagSf, smap) = UIndirectList<scalar>(tgtMagSf_, smap) =
UIndirectList<scalar>(newTgtMagSf, smap); UIndirectList<scalar>(newTgtMagSf, smap);
} }
} }

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2013-2016 OpenFOAM Foundation Copyright (C) 2013-2016 OpenFOAM Foundation
Copyright (C) 2016 OpenCFD Ltd. Copyright (C) 2016-2020 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -49,19 +49,15 @@ namespace Foam
Class partialFaceAreaWeightAMI Declaration Class partialFaceAreaWeightAMI Declaration
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
template<class SourcePatch, class TargetPatch>
class partialFaceAreaWeightAMI class partialFaceAreaWeightAMI
: :
public faceAreaWeightAMI<SourcePatch, TargetPatch> public faceAreaWeightAMI
{ {
private: private:
// Private Member Functions // Private Member Functions
//- No copy construct
partialFaceAreaWeightAMI(const partialFaceAreaWeightAMI&) = delete;
//- No copy assignment //- No copy assignment
void operator=(const partialFaceAreaWeightAMI&) = delete; void operator=(const partialFaceAreaWeightAMI&) = delete;
@ -71,7 +67,7 @@ protected:
// Protected Member Functions // Protected Member Functions
//- Set the source and target seed faces //- Set the source and target seed faces
virtual void setNextFaces virtual bool setNextFaces
( (
label& startSeedi, label& startSeedi,
label& srcFacei, label& srcFacei,
@ -91,16 +87,34 @@ public:
// Constructors // Constructors
//- Construct from dictionary
partialFaceAreaWeightAMI
(
const dictionary& dict,
const bool reverseTarget = false
);
//- Construct from components //- Construct from components
partialFaceAreaWeightAMI partialFaceAreaWeightAMI
( (
const SourcePatch& srcPatch, const bool requireMatch = false,
const TargetPatch& tgtPatch,
const faceAreaIntersect::triangulationMode& triMode,
const bool reverseTarget = false, const bool reverseTarget = false,
const bool requireMatch = true const scalar lowWeightCorrection = -1,
const faceAreaIntersect::triangulationMode triMode =
faceAreaIntersect::tmMesh,
const bool restartUncoveredSourceFace = true
); );
//- Construct as copy
partialFaceAreaWeightAMI(const partialFaceAreaWeightAMI& ami);
//- Construct and return a clone
virtual autoPtr<AMIInterpolation> clone() const
{
return
autoPtr<AMIInterpolation>(new partialFaceAreaWeightAMI(*this));
}
//- Destructor //- Destructor
virtual ~partialFaceAreaWeightAMI() = default; virtual ~partialFaceAreaWeightAMI() = default;
@ -108,29 +122,16 @@ public:
// Member Functions // Member Functions
// Access //- Flag to indicate that interpolation patches are conformal
virtual bool conformal() const;
//- Flag to indicate that interpolation patches are conformal //- Update addressing, weights and (optional) centroids
virtual bool conformal() const; virtual bool calculate
(
const primitivePatch& srcPatch,
// Manipulation const primitivePatch& tgtPatch,
const autoPtr<searchableSurface>& surfPtr = nullptr
//- Update addressing and weights );
virtual bool calculate
(
labelListList& srcAddress,
scalarListList& srcWeights,
pointListList& srcCentroids,
labelListList& tgtAddress,
scalarListList& tgtWeights,
scalarList& srcMagSf,
scalarList& tgtMagSf,
autoPtr<mapDistribute>& srcMapPtr,
autoPtr<mapDistribute>& tgtMapPtr,
label srcFacei = -1,
label tgtFacei = -1
);
}; };
@ -140,12 +141,6 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "partialFaceAreaWeightAMI.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif #endif
// ************************************************************************* // // ************************************************************************* //

View File

@ -46,6 +46,7 @@ SourceFiles
#include "face.H" #include "face.H"
#include "triPoints.H" #include "triPoints.H"
#include "Enum.H" #include "Enum.H"
#include "searchableSurface.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2013-2016 OpenFOAM Foundation Copyright (C) 2013-2016 OpenFOAM Foundation
Copyright (C) 2017-2019 OpenCFD Ltd. Copyright (C) 2017-2020 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -72,20 +72,13 @@ void Foam::cyclicACMIPolyPatch::reportCoverage
} }
void Foam::cyclicACMIPolyPatch::resetAMI void Foam::cyclicACMIPolyPatch::resetAMI() const
(
const AMIPatchToPatchInterpolation::interpolationMethod& AMIMethod
) const
{ {
resetAMI(boundaryMesh().mesh().points(), AMIMethod); resetAMI(boundaryMesh().mesh().points());
} }
void Foam::cyclicACMIPolyPatch::resetAMI void Foam::cyclicACMIPolyPatch::resetAMI(const UList<point>& points) const
(
const UList<point>& points,
const AMIPatchToPatchInterpolation::interpolationMethod& AMIMethod
) const
{ {
if (!owner()) if (!owner())
{ {
@ -94,52 +87,40 @@ void Foam::cyclicACMIPolyPatch::resetAMI
const polyPatch& nonOverlapPatch = this->nonOverlapPatch(); const polyPatch& nonOverlapPatch = this->nonOverlapPatch();
if (debug) DebugPout
<< "cyclicACMIPolyPatch::resetAMI : recalculating weights"
<< " for " << name() << " and " << nonOverlapPatch.name()
<< endl;
const polyMesh& mesh = boundaryMesh().mesh();
if (!createAMIFaces_ && mesh.hasCellCentres())
{ {
Pout<< "cyclicACMIPolyPatch::resetAMI : recalculating weights" DebugPout
<< "cyclicACMIPolyPatch::resetAMI : clearing cellCentres"
<< " for " << name() << " and " << nonOverlapPatch.name() << " for " << name() << " and " << nonOverlapPatch.name()
<< endl; << endl;
}
WarningInFunction
WarningInFunction<< "DEACTIVATED clearGeom()" << endl; << "The mesh already has cellCentres calculated when"
// if (boundaryMesh().mesh().hasCellCentres()) << " resetting ACMI " << name() << "." << nl
if (0 && boundaryMesh().mesh().hasCellCentres()) << "This is a problem since ACMI adapts the face areas"
{ << " (to close cells) so this has" << nl
if (debug) << "to be done before cell centre calculation." << nl
{ << "This can happen if e.g. the cyclicACMI is after"
Pout<< "cyclicACMIPolyPatch::resetAMI : clearing cellCentres" << " any processor patches in the boundary." << endl;
<< " for " << name() << " and " << nonOverlapPatch.name() const_cast<polyMesh&>(mesh).primitiveMesh::clearGeom();
<< endl;
}
//WarningInFunction
// << "The mesh already has cellCentres calculated when"
// << " resetting ACMI " << name() << "." << endl
// << "This is a problem since ACMI adapts the face areas"
// << " (to close cells) so this has" << endl
// << "to be done before cell centre calculation." << endl
// << "This can happen if e.g. the cyclicACMI is after"
// << " any processor patches in the boundary." << endl;
const_cast<polyMesh&>
(
boundaryMesh().mesh()
).primitiveMesh::clearGeom();
} }
// Trigger re-building of faceAreas // Trigger re-building of faceAreas
(void)boundaryMesh().mesh().faceAreas(); (void)mesh.faceAreas();
// Calculate the AMI using partial face-area-weighted. This leaves // Calculate the AMI using partial face-area-weighted. This leaves
// the weights as fractions of local areas (sum(weights) = 1 means // the weights as fractions of local areas (sum(weights) = 1 means
// face is fully covered) // face is fully covered)
cyclicAMIPolyPatch::resetAMI cyclicAMIPolyPatch::resetAMI(points);
(
points,
AMIPatchToPatchInterpolation::imPartialFaceAreaWeight
);
const AMIPatchToPatchInterpolation& AMI = this->AMI(); const AMIPatchToPatchInterpolation& AMI = this->AMI();
@ -196,15 +177,17 @@ void Foam::cyclicACMIPolyPatch::scalePatchFaceAreas
// Primitive patch face areas have been cleared/reset based on the raw // Primitive patch face areas have been cleared/reset based on the raw
// points - need to reset to avoid double-accounting of face areas // points - need to reset to avoid double-accounting of face areas
DebugPout
<< "rescaling non-overlap patch areas" << endl;
const scalar maxTol = scalar(1) - tolerance_; const scalar maxTol = scalar(1) - tolerance_;
const scalarField& mask = acmipp.mask(); const scalarField& mask = acmipp.mask();
const polyPatch& nonOverlapPatch = acmipp.nonOverlapPatch(); const polyPatch& nonOverlapPatch = acmipp.nonOverlapPatch();
vectorField::subField noSf = nonOverlapPatch.faceAreas(); vectorField::subField noSf = nonOverlapPatch.faceAreas();
DebugPout
<< "rescaling non-overlap patch areas for: " << nonOverlapPatch.name()
<< endl;
if (mask.size() != noSf.size()) if (mask.size() != noSf.size())
{ {
WarningInFunction WarningInFunction
@ -232,7 +215,7 @@ void Foam::cyclicACMIPolyPatch::scalePatchFaceAreas
// updates, e.g. by the calls to cyclicAMIPolyPatch's setTopology and // updates, e.g. by the calls to cyclicAMIPolyPatch's setTopology and
// initMovePoints // initMovePoints
DebugPout DebugPout
<< "scaling coupled patch areas" << endl; << "scaling coupled patch areas for: " << acmipp.name() << endl;
// Scale the coupled patch face areas // Scale the coupled patch face areas
vectorField::subField Sf = acmipp.faceAreas(); vectorField::subField Sf = acmipp.faceAreas();
@ -266,26 +249,26 @@ void Foam::cyclicACMIPolyPatch::scalePatchFaceAreas
void Foam::cyclicACMIPolyPatch::initGeometry(PstreamBuffers& pBufs) void Foam::cyclicACMIPolyPatch::initGeometry(PstreamBuffers& pBufs)
{ {
if (debug) DebugPout << "cyclicACMIPolyPatch::initGeometry : " << name() << endl;
{
Pout<< "cyclicACMIPolyPatch::initGeometry : " << name() << endl;
}
// Note: calculates transformation and triggers face centre calculation // Note: calculates transformation and triggers face centre calculation
cyclicAMIPolyPatch::initGeometry(pBufs); cyclicAMIPolyPatch::initGeometry(pBufs);
// On start-up there are no topological updates so scale the face areas // Initialise the AMI early to make sure we adapt the face areas before the
// - Note: resetAMI called by cyclicAMIPolyPatch::initGeometry // cell centre calculation gets triggered.
if (!createAMIFaces_ && canResetAMI())
{
resetAMI();
}
scalePatchFaceAreas(); scalePatchFaceAreas();
} }
void Foam::cyclicACMIPolyPatch::calcGeometry(PstreamBuffers& pBufs) void Foam::cyclicACMIPolyPatch::calcGeometry(PstreamBuffers& pBufs)
{ {
if (debug) DebugPout << "cyclicACMIPolyPatch::calcGeometry : " << name() << endl;
{
Pout<< "cyclicACMIPolyPatch::calcGeometry : " << name() << endl;
}
cyclicAMIPolyPatch::calcGeometry(pBufs); cyclicAMIPolyPatch::calcGeometry(pBufs);
} }
@ -296,10 +279,7 @@ void Foam::cyclicACMIPolyPatch::initMovePoints
const pointField& p const pointField& p
) )
{ {
if (debug) DebugPout<< "cyclicACMIPolyPatch::initMovePoints : " << name() << endl;
{
Pout<< "cyclicACMIPolyPatch::initMovePoints : " << name() << endl;
}
// Note: calculates transformation and triggers face centre calculation // Note: calculates transformation and triggers face centre calculation
// - Note: resetAMI called by cyclicAMIPolyPatch::initMovePoints // - Note: resetAMI called by cyclicAMIPolyPatch::initMovePoints
@ -315,10 +295,7 @@ void Foam::cyclicACMIPolyPatch::movePoints
const pointField& p const pointField& p
) )
{ {
if (debug) DebugPout << "cyclicACMIPolyPatch::movePoints : " << name() << endl;
{
Pout<< "cyclicACMIPolyPatch::movePoints : " << name() << endl;
}
// When topology is changing, this will scale the duplicate AMI faces // When topology is changing, this will scale the duplicate AMI faces
cyclicAMIPolyPatch::movePoints(pBufs, p); cyclicAMIPolyPatch::movePoints(pBufs, p);
@ -327,30 +304,24 @@ void Foam::cyclicACMIPolyPatch::movePoints
void Foam::cyclicACMIPolyPatch::initUpdateMesh(PstreamBuffers& pBufs) void Foam::cyclicACMIPolyPatch::initUpdateMesh(PstreamBuffers& pBufs)
{ {
if (debug) DebugPout << "cyclicACMIPolyPatch::initUpdateMesh : " << name() << endl;
{
Pout<< "cyclicACMIPolyPatch::initUpdateMesh : " << name() << endl;
}
cyclicAMIPolyPatch::initUpdateMesh(pBufs); cyclicAMIPolyPatch::initUpdateMesh(pBufs);
} }
void Foam::cyclicACMIPolyPatch::updateMesh(PstreamBuffers& pBufs) void Foam::cyclicACMIPolyPatch::updateMesh(PstreamBuffers& pBufs)
{ {
if (debug) DebugPout << "cyclicACMIPolyPatch::updateMesh : " << name() << endl;
{
Pout<< "cyclicACMIPolyPatch::updateMesh : " << name() << endl;
}
cyclicAMIPolyPatch::updateMesh(pBufs); cyclicAMIPolyPatch::updateMesh(pBufs);
} }
void Foam::cyclicACMIPolyPatch::clearGeom() void Foam::cyclicACMIPolyPatch::clearGeom()
{ {
if (debug) DebugPout << "cyclicACMIPolyPatch::clearGeom : " << name() << endl;
{
Pout<< "cyclicACMIPolyPatch::clearGeom : " << name() << endl;
}
cyclicAMIPolyPatch::clearGeom(); cyclicAMIPolyPatch::clearGeom();
} }
@ -377,16 +348,27 @@ Foam::cyclicACMIPolyPatch::cyclicACMIPolyPatch
const label index, const label index,
const polyBoundaryMesh& bm, const polyBoundaryMesh& bm,
const word& patchType, const word& patchType,
const transformType transform const transformType transform,
const word& defaultAMIMethod
) )
: :
cyclicAMIPolyPatch(name, size, start, index, bm, patchType, transform), cyclicAMIPolyPatch
(
name,
size,
start,
index,
bm,
patchType,
transform,
defaultAMIMethod
),
nonOverlapPatchName_(word::null), nonOverlapPatchName_(word::null),
nonOverlapPatchID_(-1), nonOverlapPatchID_(-1),
srcMask_(), srcMask_(),
tgtMask_() tgtMask_()
{ {
AMIRequireMatch_ = false; AMIPtr_->setRequireMatch(false);
// Non-overlapping patch might not be valid yet so cannot determine // Non-overlapping patch might not be valid yet so cannot determine
// associated patchID // associated patchID
@ -399,16 +381,17 @@ Foam::cyclicACMIPolyPatch::cyclicACMIPolyPatch
const dictionary& dict, const dictionary& dict,
const label index, const label index,
const polyBoundaryMesh& bm, const polyBoundaryMesh& bm,
const word& patchType const word& patchType,
const word& defaultAMIMethod
) )
: :
cyclicAMIPolyPatch(name, dict, index, bm, patchType), cyclicAMIPolyPatch(name, dict, index, bm, patchType, defaultAMIMethod),
nonOverlapPatchName_(dict.lookup("nonOverlapPatch")), nonOverlapPatchName_(dict.get<word>("nonOverlapPatch")),
nonOverlapPatchID_(-1), nonOverlapPatchID_(-1),
srcMask_(), srcMask_(),
tgtMask_() tgtMask_()
{ {
AMIRequireMatch_ = false; AMIPtr_->setRequireMatch(false);
if (nonOverlapPatchName_ == name) if (nonOverlapPatchName_ == name)
{ {
@ -435,7 +418,7 @@ Foam::cyclicACMIPolyPatch::cyclicACMIPolyPatch
srcMask_(), srcMask_(),
tgtMask_() tgtMask_()
{ {
AMIRequireMatch_ = false; AMIPtr_->setRequireMatch(false);
// Non-overlapping patch might not be valid yet so cannot determine // Non-overlapping patch might not be valid yet so cannot determine
// associated patchID // associated patchID
@ -459,7 +442,7 @@ Foam::cyclicACMIPolyPatch::cyclicACMIPolyPatch
srcMask_(), srcMask_(),
tgtMask_() tgtMask_()
{ {
AMIRequireMatch_ = false; AMIPtr_->setRequireMatch(false);
if (nonOverlapPatchName_ == name()) if (nonOverlapPatchName_ == name())
{ {
@ -489,7 +472,7 @@ Foam::cyclicACMIPolyPatch::cyclicACMIPolyPatch
srcMask_(), srcMask_(),
tgtMask_() tgtMask_()
{ {
AMIRequireMatch_ = false; AMIPtr_->setRequireMatch(false);
} }

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2013-2016 OpenFOAM Foundation Copyright (C) 2013-2016 OpenFOAM Foundation
Copyright (C) 2018-2019 OpenCFD Ltd. Copyright (C) 2018-2020 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -41,6 +41,7 @@ SourceFiles
#include "cyclicAMIPolyPatch.H" #include "cyclicAMIPolyPatch.H"
#include "AMIPatchToPatchInterpolation.H" #include "AMIPatchToPatchInterpolation.H"
#include "polyBoundaryMesh.H" #include "polyBoundaryMesh.H"
#include "partialFaceAreaWeightAMI.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -86,19 +87,10 @@ protected:
) const; ) const;
//- Reset the AMI interpolator, supply patch points //- Reset the AMI interpolator, supply patch points
virtual void resetAMI virtual void resetAMI(const UList<point>& points) const;
(
const UList<point>& points,
const AMIPatchToPatchInterpolation::interpolationMethod& AMIMethod =
AMIPatchToPatchInterpolation::imFaceAreaWeight
) const;
//- Reset the AMI interpolator, use current patch points //- Reset the AMI interpolator, use current patch points
virtual void resetAMI virtual void resetAMI() const;
(
const AMIPatchToPatchInterpolation::interpolationMethod& AMIMethod =
AMIPatchToPatchInterpolation::imFaceAreaWeight
) const;
//- Scale patch face areas to maintain physical area //- Scale patch face areas to maintain physical area
virtual void scalePatchFaceAreas(); virtual void scalePatchFaceAreas();
@ -145,7 +137,8 @@ public:
const label index, const label index,
const polyBoundaryMesh& bm, const polyBoundaryMesh& bm,
const word& patchType, const word& patchType,
const transformType transform = UNKNOWN const transformType transform = UNKNOWN,
const word& defaultAMIMethod = partialFaceAreaWeightAMI::typeName
); );
//- Construct from dictionary //- Construct from dictionary
@ -155,7 +148,8 @@ public:
const dictionary& dict, const dictionary& dict,
const label index, const label index,
const polyBoundaryMesh& bm, const polyBoundaryMesh& bm,
const word& patchType const word& patchType,
const word& defaultAMIMethod = partialFaceAreaWeightAMI::typeName
); );
//- Construct as copy, resetting the boundary mesh //- Construct as copy, resetting the boundary mesh

View File

@ -29,7 +29,9 @@ License
#include "cyclicAMIPolyPatch.H" #include "cyclicAMIPolyPatch.H"
#include "SubField.H" #include "SubField.H"
#include "Time.H" #include "Time.H"
#include "faceAreaIntersect.H" #include "unitConversion.H"
#include "OFstream.H"
#include "meshTools.H"
#include "addToRunTimeSelectionTable.H" #include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -59,14 +61,12 @@ Foam::vector Foam::cyclicAMIPolyPatch::findFaceNormalMaxRadius
label facei = findMax(magRadSqr); label facei = findMax(magRadSqr);
if (debug) DebugInFunction
{ << "Patch: " << name() << nl
Info<< "findFaceMaxRadius(const pointField&) : patch: " << name() << nl << " rotFace = " << facei << nl
<< " rotFace = " << facei << nl << " point = " << faceCentres[facei] << nl
<< " point = " << faceCentres[facei] << nl << " distance = " << Foam::sqrt(magRadSqr[facei])
<< " distance = " << Foam::sqrt(magRadSqr[facei]) << endl;
<< endl;
}
return n[facei]; return n[facei];
} }
@ -288,20 +288,45 @@ void Foam::cyclicAMIPolyPatch::calcTransforms
// * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * * // // * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * * //
void Foam::cyclicAMIPolyPatch::resetAMI const Foam::autoPtr<Foam::searchableSurface>&
( Foam::cyclicAMIPolyPatch::surfPtr() const
const AMIPatchToPatchInterpolation::interpolationMethod& AMIMethod
) const
{ {
resetAMI(boundaryMesh().mesh().points(), AMIMethod); const word surfType(surfDict_.getOrDefault<word>("type", "none"));
if (!surfPtr_ && owner() && surfType != "none")
{
word surfName(surfDict_.getOrDefault("name", name()));
const polyMesh& mesh = boundaryMesh().mesh();
surfPtr_ =
searchableSurface::New
(
surfType,
IOobject
(
surfName,
mesh.time().constant(),
"triSurface",
mesh,
IOobject::MUST_READ,
IOobject::NO_WRITE
),
surfDict_
);
}
return surfPtr_;
} }
void Foam::cyclicAMIPolyPatch::resetAMI void Foam::cyclicAMIPolyPatch::resetAMI() const
( {
const UList<point>& points, resetAMI(boundaryMesh().mesh().points());
const AMIPatchToPatchInterpolation::interpolationMethod& AMIMethod }
) const
void Foam::cyclicAMIPolyPatch::resetAMI(const UList<point>& points) const
{ {
DebugInFunction << endl; DebugInFunction << endl;
@ -310,11 +335,9 @@ void Foam::cyclicAMIPolyPatch::resetAMI
return; return;
} }
AMIPtr_.clear();
const cyclicAMIPolyPatch& nbr = neighbPatch(); const cyclicAMIPolyPatch& nbr = neighbPatch();
pointField srcPoints(points, meshPoints()); pointField srcPoints(localPoints());
pointField nbrPoints(points, neighbPatch().meshPoints()); pointField nbrPoints(nbr.localPoints());
if (debug) if (debug)
{ {
@ -343,20 +366,12 @@ void Foam::cyclicAMIPolyPatch::resetAMI
transformPosition(nbrPoints); transformPosition(nbrPoints);
primitivePatch nbrPatch0 primitivePatch nbrPatch0
( (
SubList<face> SubList<face>(nbr.localFaces(), nbrPatchSize0),
(
nbr.localFaces(),
nbrPatchSize0
),
nbrPoints nbrPoints
); );
primitivePatch patch0 primitivePatch patch0
( (
SubList<face> SubList<face>(localFaces(), patchSize0),
(
localFaces(),
patchSize0
),
srcPoints srcPoints
); );
@ -372,23 +387,8 @@ void Foam::cyclicAMIPolyPatch::resetAMI
} }
// Construct/apply AMI interpolation to determine addressing and weights // Construct/apply AMI interpolation to determine addressing and weights
AMIPtr_.reset AMIPtr_->upToDate() = false;
( AMIPtr_->calculate(patch0, nbrPatch0, surfPtr());
new AMIPatchToPatchInterpolation
(
patch0, // *this,
nbrPatch0,
surfPtr(),
faceAreaIntersect::tmMesh,
AMIRequireMatch_,
AMIMethod,
AMILowWeightCorrection_,
AMIReverse_
)
);
// Set the updated flag
updated_ = true;
if (debug) if (debug)
{ {
@ -424,14 +424,12 @@ void Foam::cyclicAMIPolyPatch::calcTransforms()
half1Areas half1Areas
); );
if (debug) DebugPout
{ << "calcTransforms() : patch: " << name() << nl
Pout<< "calcTransforms() : patch: " << name() << nl << " forwardT = " << forwardT() << nl
<< " forwardT = " << forwardT() << nl << " reverseT = " << reverseT() << nl
<< " reverseT = " << reverseT() << nl << " separation = " << separation() << nl
<< " separation = " << separation() << nl << " collocated = " << collocated() << nl << endl;
<< " collocated = " << collocated() << nl << endl;
}
} }
@ -439,13 +437,8 @@ void Foam::cyclicAMIPolyPatch::initGeometry(PstreamBuffers& pBufs)
{ {
DebugInFunction << endl; DebugInFunction << endl;
// Only resetting the AMI if not creating additional AMI faces // Flag AMI as needing update
// - When creating additional faces the AMI is updated externally by the AMIPtr_->upToDate() = false;
// dynamic mesh via the setTopology function.
if (!createAMIFaces_ && canResetAMI())
{
resetAMI(AMIMethod_);
}
polyPatch::initGeometry(pBufs); polyPatch::initGeometry(pBufs);
@ -491,7 +484,7 @@ void Foam::cyclicAMIPolyPatch::initMovePoints
} }
else else
{ {
resetAMI(p, AMIMethod_); AMIPtr_->upToDate() = false;
} }
// Early calculation of transforms. See above. // Early calculation of transforms. See above.
@ -551,9 +544,9 @@ void Foam::cyclicAMIPolyPatch::clearGeom()
if (!updatingAMI_) if (!updatingAMI_)
{ {
//DEBUG("*** CLEARING AMI ***"); AMIPtr_->upToDate() = false;
AMIPtr_.clear();
} }
polyPatch::clearGeom(); polyPatch::clearGeom();
} }
@ -568,11 +561,11 @@ Foam::cyclicAMIPolyPatch::cyclicAMIPolyPatch
const label index, const label index,
const polyBoundaryMesh& bm, const polyBoundaryMesh& bm,
const word& patchType, const word& patchType,
const transformType transform const transformType transform,
const word& defaultAMIMethod
) )
: :
coupledPolyPatch(name, size, start, index, bm, patchType, transform), coupledPolyPatch(name, size, start, index, bm, patchType, transform),
updated_(false),
nbrPatchName_(word::null), nbrPatchName_(word::null),
nbrPatchID_(-1), nbrPatchID_(-1),
rotationAxis_(Zero), rotationAxis_(Zero),
@ -580,14 +573,11 @@ Foam::cyclicAMIPolyPatch::cyclicAMIPolyPatch
rotationAngleDefined_(false), rotationAngleDefined_(false),
rotationAngle_(0.0), rotationAngle_(0.0),
separationVector_(Zero), separationVector_(Zero),
AMIPtr_(nullptr), AMIPtr_(AMIInterpolation::New(defaultAMIMethod)),
AMIMethod_(AMIPatchToPatchInterpolation::imFaceAreaWeight),
AMIReverse_(false),
AMIRequireMatch_(true),
AMILowWeightCorrection_(-1.0),
surfPtr_(nullptr),
surfDict_(fileName("surface")), surfDict_(fileName("surface")),
surfPtr_(nullptr),
createAMIFaces_(false), createAMIFaces_(false),
moveFaceCentres_(false),
updatingAMI_(true), updatingAMI_(true),
srcFaceIDs_(), srcFaceIDs_(),
tgtFaceIDs_(), tgtFaceIDs_(),
@ -605,12 +595,12 @@ Foam::cyclicAMIPolyPatch::cyclicAMIPolyPatch
const dictionary& dict, const dictionary& dict,
const label index, const label index,
const polyBoundaryMesh& bm, const polyBoundaryMesh& bm,
const word& patchType const word& patchType,
const word& defaultAMIMethod
) )
: :
coupledPolyPatch(name, dict, index, bm, patchType), coupledPolyPatch(name, dict, index, bm, patchType),
updated_(false), nbrPatchName_(dict.getOrDefault<word>("neighbourPatch", word::null)),
nbrPatchName_(dict.getOrDefault<word>("neighbourPatch", "")),
coupleGroup_(dict), coupleGroup_(dict),
nbrPatchID_(-1), nbrPatchID_(-1),
rotationAxis_(Zero), rotationAxis_(Zero),
@ -618,27 +608,19 @@ Foam::cyclicAMIPolyPatch::cyclicAMIPolyPatch
rotationAngleDefined_(false), rotationAngleDefined_(false),
rotationAngle_(0.0), rotationAngle_(0.0),
separationVector_(Zero), separationVector_(Zero),
AMIPtr_(nullptr), AMIPtr_
AMIMethod_
( (
AMIPatchToPatchInterpolation::interpolationMethodNames_ AMIInterpolation::New
[ (
dict.getOrDefault dict.getOrDefault<word>("AMIMethod", defaultAMIMethod),
( dict,
"method", dict.getOrDefault("flipNormals", false)
AMIPatchToPatchInterpolation::interpolationMethodNames_ )
[
AMIPatchToPatchInterpolation::imFaceAreaWeight
]
)
]
), ),
AMIReverse_(dict.getOrDefault("flipNormals", false)),
AMIRequireMatch_(true),
AMILowWeightCorrection_(dict.getOrDefault("lowWeightCorrection", -1.0)),
surfPtr_(nullptr),
surfDict_(dict.subOrEmptyDict("surface")), surfDict_(dict.subOrEmptyDict("surface")),
createAMIFaces_(false), surfPtr_(nullptr),
createAMIFaces_(dict.getOrDefault("createAMIFaces", false)),
moveFaceCentres_(false),
updatingAMI_(true), updatingAMI_(true),
srcFaceIDs_(), srcFaceIDs_(),
tgtFaceIDs_(), tgtFaceIDs_(),
@ -704,18 +686,13 @@ Foam::cyclicAMIPolyPatch::cyclicAMIPolyPatch
// Neighbour patch might not be valid yet so no transformation // Neighbour patch might not be valid yet so no transformation
// calculation possible // calculation possible
// If topology change, recover the sizes of the original patches // If topology change, recover the sizes of the original patches and
label srcSize0 = 0; // read additional controls
if (dict.readIfPresent("srcSize", srcSize0)) if (createAMIFaces_)
{ {
srcFaceIDs_.setSize(srcSize0); srcFaceIDs_.setSize(dict.get<label>("srcSize"));
createAMIFaces_ = true; tgtFaceIDs_.setSize(dict.get<label>("tgtSize"));
} moveFaceCentres_ = dict.getOrDefault("moveFaceCentres", true);
label tgtSize0 = 0;
if (dict.readIfPresent("tgtSize", tgtSize0))
{
tgtFaceIDs_.setSize(tgtSize0);
createAMIFaces_ = true;
} }
} }
@ -727,7 +704,6 @@ Foam::cyclicAMIPolyPatch::cyclicAMIPolyPatch
) )
: :
coupledPolyPatch(pp, bm), coupledPolyPatch(pp, bm),
updated_(false),
nbrPatchName_(pp.nbrPatchName_), nbrPatchName_(pp.nbrPatchName_),
coupleGroup_(pp.coupleGroup_), coupleGroup_(pp.coupleGroup_),
nbrPatchID_(-1), nbrPatchID_(-1),
@ -736,14 +712,11 @@ Foam::cyclicAMIPolyPatch::cyclicAMIPolyPatch
rotationAngleDefined_(pp.rotationAngleDefined_), rotationAngleDefined_(pp.rotationAngleDefined_),
rotationAngle_(pp.rotationAngle_), rotationAngle_(pp.rotationAngle_),
separationVector_(pp.separationVector_), separationVector_(pp.separationVector_),
AMIPtr_(nullptr), AMIPtr_(pp.AMIPtr_->clone()),
AMIMethod_(pp.AMIMethod_),
AMIReverse_(pp.AMIReverse_),
AMIRequireMatch_(pp.AMIRequireMatch_),
AMILowWeightCorrection_(pp.AMILowWeightCorrection_),
surfPtr_(nullptr),
surfDict_(pp.surfDict_), surfDict_(pp.surfDict_),
createAMIFaces_(false), surfPtr_(nullptr),
createAMIFaces_(pp.createAMIFaces_),
moveFaceCentres_(pp.moveFaceCentres_),
updatingAMI_(true), updatingAMI_(true),
srcFaceIDs_(), srcFaceIDs_(),
tgtFaceIDs_(), tgtFaceIDs_(),
@ -766,7 +739,6 @@ Foam::cyclicAMIPolyPatch::cyclicAMIPolyPatch
) )
: :
coupledPolyPatch(pp, bm, index, newSize, newStart), coupledPolyPatch(pp, bm, index, newSize, newStart),
updated_(false),
nbrPatchName_(nbrPatchName), nbrPatchName_(nbrPatchName),
coupleGroup_(pp.coupleGroup_), coupleGroup_(pp.coupleGroup_),
nbrPatchID_(-1), nbrPatchID_(-1),
@ -775,14 +747,11 @@ Foam::cyclicAMIPolyPatch::cyclicAMIPolyPatch
rotationAngleDefined_(pp.rotationAngleDefined_), rotationAngleDefined_(pp.rotationAngleDefined_),
rotationAngle_(pp.rotationAngle_), rotationAngle_(pp.rotationAngle_),
separationVector_(pp.separationVector_), separationVector_(pp.separationVector_),
AMIPtr_(nullptr), AMIPtr_(pp.AMIPtr_->clone()),
AMIMethod_(pp.AMIMethod_),
AMIReverse_(pp.AMIReverse_),
AMIRequireMatch_(pp.AMIRequireMatch_),
AMILowWeightCorrection_(pp.AMILowWeightCorrection_),
surfPtr_(nullptr),
surfDict_(pp.surfDict_), surfDict_(pp.surfDict_),
createAMIFaces_(false), surfPtr_(nullptr),
createAMIFaces_(pp.createAMIFaces_),
moveFaceCentres_(pp.moveFaceCentres_),
updatingAMI_(true), updatingAMI_(true),
srcFaceIDs_(), srcFaceIDs_(),
tgtFaceIDs_(), tgtFaceIDs_(),
@ -812,7 +781,6 @@ Foam::cyclicAMIPolyPatch::cyclicAMIPolyPatch
) )
: :
coupledPolyPatch(pp, bm, index, mapAddressing, newStart), coupledPolyPatch(pp, bm, index, mapAddressing, newStart),
updated_(false),
nbrPatchName_(pp.nbrPatchName_), nbrPatchName_(pp.nbrPatchName_),
coupleGroup_(pp.coupleGroup_), coupleGroup_(pp.coupleGroup_),
nbrPatchID_(-1), nbrPatchID_(-1),
@ -821,14 +789,11 @@ Foam::cyclicAMIPolyPatch::cyclicAMIPolyPatch
rotationAngleDefined_(pp.rotationAngleDefined_), rotationAngleDefined_(pp.rotationAngleDefined_),
rotationAngle_(pp.rotationAngle_), rotationAngle_(pp.rotationAngle_),
separationVector_(pp.separationVector_), separationVector_(pp.separationVector_),
AMIPtr_(nullptr), AMIPtr_(pp.AMIPtr_->clone()),
AMIMethod_(pp.AMIMethod_),
AMIReverse_(pp.AMIReverse_),
AMIRequireMatch_(pp.AMIRequireMatch_),
AMILowWeightCorrection_(pp.AMILowWeightCorrection_),
surfPtr_(nullptr),
surfDict_(pp.surfDict_), surfDict_(pp.surfDict_),
createAMIFaces_(false), surfPtr_(nullptr),
createAMIFaces_(pp.createAMIFaces_),
moveFaceCentres_(pp.moveFaceCentres_),
updatingAMI_(true), updatingAMI_(true),
srcFaceIDs_(), srcFaceIDs_(),
tgtFaceIDs_(), tgtFaceIDs_(),
@ -888,38 +853,6 @@ const Foam::cyclicAMIPolyPatch& Foam::cyclicAMIPolyPatch::neighbPatch() const
} }
const Foam::autoPtr<Foam::searchableSurface>&
Foam::cyclicAMIPolyPatch::surfPtr() const
{
const word surfType(surfDict_.getOrDefault<word>("type", "none"));
if (!surfPtr_.valid() && owner() && surfType != "none")
{
word surfName(surfDict_.getOrDefault("name", name()));
const polyMesh& mesh = boundaryMesh().mesh();
surfPtr_ =
searchableSurface::New
(
surfType,
IOobject
(
surfName,
mesh.time().constant(),
"triSurface",
mesh,
IOobject::MUST_READ,
IOobject::NO_WRITE
),
surfDict_
);
}
return surfPtr_;
}
const Foam::AMIPatchToPatchInterpolation& Foam::cyclicAMIPolyPatch::AMI() const const Foam::AMIPatchToPatchInterpolation& Foam::cyclicAMIPolyPatch::AMI() const
{ {
if (!owner()) if (!owner())
@ -929,9 +862,9 @@ const Foam::AMIPatchToPatchInterpolation& Foam::cyclicAMIPolyPatch::AMI() const
<< abort(FatalError); << abort(FatalError);
} }
if (!AMIPtr_.valid()) if (!AMIPtr_->upToDate())
{ {
resetAMI(AMIMethod_); resetAMI();
} }
return *AMIPtr_; return *AMIPtr_;
@ -1206,27 +1139,7 @@ void Foam::cyclicAMIPolyPatch::write(Ostream& os) const
} }
} }
if (AMIMethod_ != AMIPatchToPatchInterpolation::imFaceAreaWeight) AMIPtr_->write(os);
{
os.writeEntry
(
"method",
AMIPatchToPatchInterpolation::interpolationMethodNames_
[
AMIMethod_
]
);
}
if (AMIReverse_)
{
os.writeEntry("flipNormals", AMIReverse_);
}
if (AMILowWeightCorrection_ > 0)
{
os.writeEntry("lowWeightCorrection", AMILowWeightCorrection_);
}
if (!surfDict_.empty()) if (!surfDict_.empty())
{ {
@ -1235,8 +1148,10 @@ void Foam::cyclicAMIPolyPatch::write(Ostream& os) const
if (createAMIFaces_) if (createAMIFaces_)
{ {
os.writeEntry("createAMIFaces", createAMIFaces_);
os.writeEntry("srcSize", srcFaceIDs_.size()); os.writeEntry("srcSize", srcFaceIDs_.size());
os.writeEntry("tgtSize", tgtFaceIDs_.size()); os.writeEntry("tgtSize", tgtFaceIDs_.size());
os.writeEntry("moveFaceCentres", moveFaceCentres_);
} }
} }

View File

@ -6,6 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2018-2020 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -41,6 +42,7 @@ SourceFiles
#include "AMIPatchToPatchInterpolation.H" #include "AMIPatchToPatchInterpolation.H"
#include "polyBoundaryMesh.H" #include "polyBoundaryMesh.H"
#include "coupleGroupIdentifier.H" #include "coupleGroupIdentifier.H"
#include "faceAreaWeightAMI.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -74,9 +76,6 @@ protected:
// Protected data // Protected data
//- Flag to indicate that AMI has been updated
mutable bool updated_;
//- Name of other half //- Name of other half
mutable word nbrPatchName_; mutable word nbrPatchName_;
@ -113,24 +112,12 @@ protected:
//- AMI interpolation class //- AMI interpolation class
mutable autoPtr<AMIPatchToPatchInterpolation> AMIPtr_; mutable autoPtr<AMIPatchToPatchInterpolation> AMIPtr_;
//- AMI method //- Dictionary used during projection surface construction
const AMIPatchToPatchInterpolation::interpolationMethod AMIMethod_; const dictionary surfDict_;
//- Flag to indicate that slave patch should be reversed for AMI
const bool AMIReverse_;
//- Flag to indicate that patches should match/overlap
bool AMIRequireMatch_;
//- Low weight correction threshold for AMI
const scalar AMILowWeightCorrection_;
//- Projection surface //- Projection surface
mutable autoPtr<searchableSurface> surfPtr_; mutable autoPtr<searchableSurface> surfPtr_;
//- Dictionary used during projection surface construction
const dictionary surfDict_;
// Change of topology as AMI is updated // Change of topology as AMI is updated
@ -138,6 +125,9 @@ protected:
// Set by the call to changeTopology // Set by the call to changeTopology
mutable bool createAMIFaces_; mutable bool createAMIFaces_;
//- Move face centres (default = no)
bool moveFaceCentres_;
mutable bool updatingAMI_; mutable bool updatingAMI_;
labelListList srcFaceIDs_; labelListList srcFaceIDs_;
@ -163,21 +153,14 @@ protected:
virtual void restoreScaledGeometry(); virtual void restoreScaledGeometry();
//- Create and return pointer to the projection surface
const autoPtr<searchableSurface>& surfPtr() const;
//- Reset the AMI interpolator, supply patch points //- Reset the AMI interpolator, supply patch points
virtual void resetAMI virtual void resetAMI(const UList<point>& points) const;
(
const UList<point>& points,
const AMIPatchToPatchInterpolation::interpolationMethod& AMIMethod =
AMIPatchToPatchInterpolation::imFaceAreaWeight
) const;
//- Reset the AMI interpolator, use current patch points //- Reset the AMI interpolator, use current patch points
virtual void resetAMI virtual void resetAMI() const;
(
const AMIPatchToPatchInterpolation::interpolationMethod& AMIMethod =
AMIPatchToPatchInterpolation::imFaceAreaWeight
) const;
//- Recalculate the transformation tensors //- Recalculate the transformation tensors
virtual void calcTransforms(); virtual void calcTransforms();
@ -221,7 +204,8 @@ public:
const label index, const label index,
const polyBoundaryMesh& bm, const polyBoundaryMesh& bm,
const word& patchType, const word& patchType,
const transformType transform = UNKNOWN const transformType transform = UNKNOWN,
const word& defaultAMIMethod = faceAreaWeightAMI::typeName
); );
//- Construct from dictionary //- Construct from dictionary
@ -231,7 +215,8 @@ public:
const dictionary& dict, const dictionary& dict,
const label index, const label index,
const polyBoundaryMesh& bm, const polyBoundaryMesh& bm,
const word& patchType const word& patchType,
const word& defaultAMIMethod = faceAreaWeightAMI::typeName
); );
//- Construct as copy, resetting the boundary mesh //- Construct as copy, resetting the boundary mesh
@ -328,23 +313,12 @@ public:
//- Flag to indicate whether the AMI can be reset //- Flag to indicate whether the AMI can be reset
inline bool canResetAMI() const; inline bool canResetAMI() const;
//- Reset the updated flag
inline void setUpdated(bool flag) const;
//- Return access to the updated flag
inline bool updated() const;
//- Return access to the createAMIFaces flag //- Return access to the createAMIFaces flag
inline bool createAMIFaces() const; inline bool createAMIFaces() const;
//- Return access to the updated flag //- Return access to the updated flag
inline bool updatingAMI() const; inline bool updatingAMI() const;
void clearAMI() const
{
AMIPtr_.clear();
}
//- Return true if this patch changes the mesh topology //- Return true if this patch changes the mesh topology
// True when createAMIFaces is true // True when createAMIFaces is true
virtual bool changeTopology() const; virtual bool changeTopology() const;
@ -371,9 +345,6 @@ void clearAMI() const
//- Return a reference to the neighbour patch //- Return a reference to the neighbour patch
virtual const cyclicAMIPolyPatch& neighbPatch() const; virtual const cyclicAMIPolyPatch& neighbPatch() const;
//- Return a reference to the projection surface
const autoPtr<searchableSurface>& surfPtr() const;
//- Return a reference to the AMI interpolator //- Return a reference to the AMI interpolator
const AMIPatchToPatchInterpolation& AMI() const; const AMIPatchToPatchInterpolation& AMI() const;

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2013 OpenFOAM Foundation Copyright (C) 2011-2013 OpenFOAM Foundation
Copyright (C) 2019 OpenCFD Ltd. Copyright (C) 2019-2020 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -34,18 +34,6 @@ inline bool Foam::cyclicAMIPolyPatch::canResetAMI() const
} }
inline void Foam::cyclicAMIPolyPatch::setUpdated(const bool flag) const
{
updated_ = flag;
}
inline bool Foam::cyclicAMIPolyPatch::updated() const
{
return updated_;
}
inline bool Foam::cyclicAMIPolyPatch::createAMIFaces() const inline bool Foam::cyclicAMIPolyPatch::createAMIFaces() const
{ {
return createAMIFaces_; return createAMIFaces_;

View File

@ -2,8 +2,10 @@
========= | ========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2019 OpenCFD Ltd. \\ / A nd | www.openfoam.com
\\/ M anipulation | \\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019-2020 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -53,29 +55,27 @@ void Foam::cyclicAMIPolyPatch::restoreScaledGeometry()
vectorField::subField faceAreas = this->faceAreas(); vectorField::subField faceAreas = this->faceAreas();
vectorField::subField faceCentres = this->faceCentres(); vectorField::subField faceCentres = this->faceCentres();
if (debug) DebugInfo
{ << "Patch:" << name() << " before: sum(mag(faceAreas)):"
Info<< "Patch:" << name() << " before: sum(mag(faceAreas)):" << gSum(mag(faceAreas)) << nl
<< gSum(mag(faceAreas)) << endl; << "Patch:" << name() << " before: sum(mag(faceAreas0)):"
Info<< "Patch:" << name() << " before: sum(mag(faceAreas0)):" << gSum(mag(faceAreas0_)) << endl;
<< gSum(mag(faceAreas0_)) << endl;
}
faceAreas = faceAreas0_; faceAreas = faceAreas0_;
Info<< "WARNING: ==============================" << endl; if (moveFaceCentres_)
Info<< "WARNING: Not updating face cell centres" << endl; {
Info<< "WARNING: ==============================" << endl; DebugInfo << "Moving face centres" << endl;
//faceCentres = faceCentres0_; faceCentres = faceCentres0_;
}
faceAreas0_.clear(); faceAreas0_.clear();
faceCentres0_.clear(); faceCentres0_.clear();
if (debug) DebugInfo
{ << "Patch:" << name() << " after: sum(mag(faceAreas)):"
Info<< "Patch:" << name() << " after: sum(mag(faceAreas)):" << gSum(mag(faceAreas)) << nl
<< gSum(mag(faceAreas)) << endl; << "Patch:" << name() << " after: sum(mag(faceAreas0)):"
Info<< "Patch:" << name() << " after: sum(mag(faceAreas0)):" << gSum(mag(faceAreas0_)) << endl;
<< gSum(mag(faceAreas0_)) << endl;
}
} }
@ -614,9 +614,9 @@ void Foam::cyclicAMIPolyPatch::setAMIFaces()
} }
} }
// Update the AMI addressing and weights to reflect the new 1-to-1 // Reset the AMI addressing and weights to reflect the new 1-to-1
// correspondence // correspondence
AMIPtr_->update AMIPtr_->reset
( (
std::move(srcToTgtMap1), std::move(srcToTgtMap1),
std::move(tgtToSrcMap1), std::move(tgtToSrcMap1),
@ -626,7 +626,9 @@ void Foam::cyclicAMIPolyPatch::setAMIFaces()
std::move(newTgtToSrcWeights) std::move(newTgtToSrcWeights)
); );
AMIPtr_->setAreas(mag(faceAreas0_), mag(nbrFaceAreas0)); // Need to set areas, e.g. for agglomeration to (re-)normalisation weights
AMIPtr_->srcMagSf() = mag(faceAreas0_);
AMIPtr_->tgtMagSf() = mag(nbrFaceAreas0);
if (debug) if (debug)
{ {
@ -660,7 +662,7 @@ bool Foam::cyclicAMIPolyPatch::setTopology(polyTopoChange& topoChange)
{ {
// Calculate the AMI using the new points // Calculate the AMI using the new points
// Note: mesh still has old points // Note: mesh still has old points
resetAMI(topoChange.points(), AMIMethod_); resetAMI(topoChange.points());
removeAMIFaces(topoChange); removeAMIFaces(topoChange);

View File

@ -26,6 +26,7 @@ License
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#include "cyclicPeriodicAMIPolyPatch.H" #include "cyclicPeriodicAMIPolyPatch.H"
#include "partialFaceAreaWeightAMI.H"
#include "addToRunTimeSelectionTable.H" #include "addToRunTimeSelectionTable.H"
// For debugging // For debugging
@ -228,10 +229,7 @@ void Foam::cyclicPeriodicAMIPolyPatch::writeOBJ
} }
void Foam::cyclicPeriodicAMIPolyPatch::resetAMI void Foam::cyclicPeriodicAMIPolyPatch::resetAMI() const
(
const AMIPatchToPatchInterpolation::interpolationMethod& AMIMethod
) const
{ {
if (owner()) if (owner())
{ {
@ -326,20 +324,8 @@ void Foam::cyclicPeriodicAMIPolyPatch::resetAMI
); );
// Construct a new AMI interpolation between the initial patch locations // Construct a new AMI interpolation between the initial patch locations
AMIPtr_.reset AMIPtr_->setRequireMatch(false);
( AMIPtr_->calculate(thisPatch0, nbrPatch0, surfPtr());
new AMIPatchToPatchInterpolation
(
thisPatch0,
nbrPatch0,
surfPtr(),
faceAreaIntersect::tmMesh,
false,
AMIPatchToPatchInterpolation::imPartialFaceAreaWeight,
AMILowWeightCorrection_,
AMIReverse_
)
);
// Number of geometry replications // Number of geometry replications
label iter(0); label iter(0);
@ -358,7 +344,6 @@ void Foam::cyclicPeriodicAMIPolyPatch::resetAMI
// Weight sum averages // Weight sum averages
scalar srcSum(gAverage(AMIPtr_->srcWeightsSum())); scalar srcSum(gAverage(AMIPtr_->srcWeightsSum()));
scalar tgtSum(gAverage(AMIPtr_->tgtWeightsSum())); scalar tgtSum(gAverage(AMIPtr_->tgtWeightsSum()));
// Direction (or rather side of AMI : this or nbr patch) of // Direction (or rather side of AMI : this or nbr patch) of
// geometry replication // geometry replication
bool direction = nTransforms_ >= 0; bool direction = nTransforms_ >= 0;
@ -520,17 +505,13 @@ void Foam::cyclicPeriodicAMIPolyPatch::resetAMI
<< "The current matchTolerance : " << matchTolerance() << "The current matchTolerance : " << matchTolerance()
<< ", sum of owner weights : " << srcSum << ", sum of owner weights : " << srcSum
<< ", sum of neighbour weights : " << tgtSum << ", sum of neighbour weights : " << tgtSum
<< "." << nl << "." << nl
<< "This is only acceptable during post-processing" << "This is only acceptable during post-processing"
<< "; not during running. Improve your mesh or increase" << "; not during running. Improve your mesh or increase"
<< " the 'matchTolerance' setting in the patch specification." << " the 'matchTolerance' setting in the patch specification."
<< endl; << endl;
} }
// Normalise the weights. Disable printing since weights are
// still areas.
AMIPtr_->normaliseWeights(true, false);
// Print some statistics // Print some statistics
const label nFace = returnReduce(size(), sumOp<label>()); const label nFace = returnReduce(size(), sumOp<label>());
@ -577,7 +558,17 @@ Foam::cyclicPeriodicAMIPolyPatch::cyclicPeriodicAMIPolyPatch
const transformType transform const transformType transform
) )
: :
cyclicAMIPolyPatch(name, size, start, index, bm, patchType, transform), cyclicAMIPolyPatch
(
name,
size,
start,
index,
bm,
patchType,
transform,
partialFaceAreaWeightAMI::typeName
),
periodicPatchName_(word::null), periodicPatchName_(word::null),
periodicPatchID_(-1), periodicPatchID_(-1),
nTransforms_(0), nTransforms_(0),
@ -595,7 +586,15 @@ Foam::cyclicPeriodicAMIPolyPatch::cyclicPeriodicAMIPolyPatch
const word& patchType const word& patchType
) )
: :
cyclicAMIPolyPatch(name, dict, index, bm, patchType), cyclicAMIPolyPatch
(
name,
dict,
index,
bm,
patchType,
partialFaceAreaWeightAMI::typeName
),
periodicPatchName_(dict.lookup("periodicPatch")), periodicPatchName_(dict.lookup("periodicPatch")),
periodicPatchID_(-1), periodicPatchID_(-1),
nTransforms_(dict.getOrDefault<label>("nTransforms", 0)), nTransforms_(dict.getOrDefault<label>("nTransforms", 0)),

View File

@ -83,11 +83,7 @@ private:
void writeOBJ(const primitivePatch& p, OBJstream& str) const; void writeOBJ(const primitivePatch& p, OBJstream& str) const;
//- Reset the AMI interpolator //- Reset the AMI interpolator
virtual void resetAMI virtual void resetAMI() const;
(
const AMIPatchToPatchInterpolation::interpolationMethod& AMIMethod =
AMIPatchToPatchInterpolation::imFaceAreaWeight
) const;
public: public:

View File

@ -259,8 +259,13 @@ processorLOD/cellBox/cellBox.C
processorLOD/faceBox/faceBox.C processorLOD/faceBox/faceBox.C
AMI=AMIInterpolation AMI=AMIInterpolation
$(AMI)/AMIInterpolation/AMIInterpolationName.C $(AMI)/AMIInterpolation/AMIInterpolation.C
$(AMI)/AMIInterpolation/AMIPatchToPatchInterpolation.C $(AMI)/AMIInterpolation/AMIInterpolationNew.C
$(AMI)/AMIInterpolation/advancingFrontAMI/advancingFrontAMI.C
$(AMI)/AMIInterpolation/advancingFrontAMI/advancingFrontAMIParallelOps.C
$(AMI)/AMIInterpolation/faceAreaWeightAMI/faceAreaWeightAMI.C
$(AMI)/AMIInterpolation/partialFaceAreaWeightAMI/partialFaceAreaWeightAMI.C
$(AMI)/AMIInterpolation/nearestFaceAMI/nearestFaceAMI.C
$(AMI)/faceAreaIntersect/faceAreaIntersect.C $(AMI)/faceAreaIntersect/faceAreaIntersect.C
$(AMI)/GAMG/interfaces/cyclicAMIGAMGInterface/cyclicAMIGAMGInterface.C $(AMI)/GAMG/interfaces/cyclicAMIGAMGInterface/cyclicAMIGAMGInterface.C
$(AMI)/GAMG/interfaceFields/cyclicAMIGAMGInterfaceField/cyclicAMIGAMGInterfaceField.C $(AMI)/GAMG/interfaceFields/cyclicAMIGAMGInterfaceField/cyclicAMIGAMGInterfaceField.C

View File

@ -45,6 +45,7 @@ License
#include "syncTools.H" #include "syncTools.H"
#include "treeDataCell.H" #include "treeDataCell.H"
#include "DynamicField.H" #include "DynamicField.H"
#include "faceAreaWeightAMI.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -791,15 +792,13 @@ const
void Foam::mappedPatchBase::calcAMI() const void Foam::mappedPatchBase::calcAMI() const
{ {
if (AMIPtr_.valid()) if (AMIPtr_->upToDate())
{ {
FatalErrorInFunction WarningInFunction
<< "AMI already calculated" << exit(FatalError); << "AMI already up-to-date"
<< endl;
} }
AMIPtr_.clear();
const polyPatch& nbr = samplePolyPatch(); const polyPatch& nbr = samplePolyPatch();
// Transform neighbour patch to local system // Transform neighbour patch to local system
@ -829,29 +828,13 @@ void Foam::mappedPatchBase::calcAMI() const
} }
// Construct/apply AMI interpolation to determine addressing and weights // Construct/apply AMI interpolation to determine addressing and weights
AMIPtr_.reset AMIPtr_->calculate(patch_, nbrPatch0, surfPtr());
(
new AMIPatchToPatchInterpolation
(
patch_,
nbrPatch0,
surfPtr(),
faceAreaIntersect::tmMesh,
true,
AMIPatchToPatchInterpolation::imFaceAreaWeight,
-1,
AMIReverse_
)
);
} }
// * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * * * * * //
Foam::mappedPatchBase::mappedPatchBase Foam::mappedPatchBase::mappedPatchBase(const polyPatch& pp)
(
const polyPatch& pp
)
: :
patch_(pp), patch_(pp),
sampleRegion_(patch_.boundaryMesh().mesh().name()), sampleRegion_(patch_.boundaryMesh().mesh().name()),
@ -864,8 +847,8 @@ Foam::mappedPatchBase::mappedPatchBase
distance_(0), distance_(0),
sameRegion_(sampleRegion_ == patch_.boundaryMesh().mesh().name()), sameRegion_(sampleRegion_ == patch_.boundaryMesh().mesh().name()),
mapPtr_(nullptr), mapPtr_(nullptr),
AMIPtr_(nullptr),
AMIReverse_(false), AMIReverse_(false),
AMIPtr_(new faceAreaWeightAMI(true, AMIReverse_)),
surfPtr_(nullptr), surfPtr_(nullptr),
surfDict_(fileName("surface")) surfDict_(fileName("surface"))
{} {}
@ -891,8 +874,8 @@ Foam::mappedPatchBase::mappedPatchBase
distance_(0), distance_(0),
sameRegion_(sampleRegion_ == patch_.boundaryMesh().mesh().name()), sameRegion_(sampleRegion_ == patch_.boundaryMesh().mesh().name()),
mapPtr_(nullptr), mapPtr_(nullptr),
AMIPtr_(nullptr),
AMIReverse_(false), AMIReverse_(false),
AMIPtr_(new faceAreaWeightAMI(true, AMIReverse_)),
surfPtr_(nullptr), surfPtr_(nullptr),
surfDict_(fileName("surface")) surfDict_(fileName("surface"))
{} {}
@ -918,8 +901,8 @@ Foam::mappedPatchBase::mappedPatchBase
distance_(0), distance_(0),
sameRegion_(sampleRegion_ == patch_.boundaryMesh().mesh().name()), sameRegion_(sampleRegion_ == patch_.boundaryMesh().mesh().name()),
mapPtr_(nullptr), mapPtr_(nullptr),
AMIPtr_(nullptr),
AMIReverse_(false), AMIReverse_(false),
AMIPtr_(new faceAreaWeightAMI(true, AMIReverse_)),
surfPtr_(nullptr), surfPtr_(nullptr),
surfDict_(fileName("surface")) surfDict_(fileName("surface"))
{} {}
@ -945,8 +928,8 @@ Foam::mappedPatchBase::mappedPatchBase
distance_(distance), distance_(distance),
sameRegion_(sampleRegion_ == patch_.boundaryMesh().mesh().name()), sameRegion_(sampleRegion_ == patch_.boundaryMesh().mesh().name()),
mapPtr_(nullptr), mapPtr_(nullptr),
AMIPtr_(nullptr),
AMIReverse_(false), AMIReverse_(false),
AMIPtr_(new faceAreaWeightAMI(true, AMIReverse_)),
surfPtr_(nullptr), surfPtr_(nullptr),
surfDict_(fileName("surface")) surfDict_(fileName("surface"))
{} {}
@ -969,8 +952,16 @@ Foam::mappedPatchBase::mappedPatchBase
distance_(0), distance_(0),
sameRegion_(sampleRegion_ == patch_.boundaryMesh().mesh().name()), sameRegion_(sampleRegion_ == patch_.boundaryMesh().mesh().name()),
mapPtr_(nullptr), mapPtr_(nullptr),
AMIPtr_(nullptr),
AMIReverse_(dict.getOrDefault("flipNormals", false)), AMIReverse_(dict.getOrDefault("flipNormals", false)),
AMIPtr_
(
AMIInterpolation::New
(
dict.getOrDefault("AMIMethod", faceAreaWeightAMI::typeName),
dict,
AMIReverse_
)
),
surfPtr_(nullptr), surfPtr_(nullptr),
surfDict_(dict.subOrEmptyDict("surface")) surfDict_(dict.subOrEmptyDict("surface"))
{ {
@ -1044,8 +1035,16 @@ Foam::mappedPatchBase::mappedPatchBase
distance_(0), distance_(0),
sameRegion_(sampleRegion_ == patch_.boundaryMesh().mesh().name()), sameRegion_(sampleRegion_ == patch_.boundaryMesh().mesh().name()),
mapPtr_(nullptr), mapPtr_(nullptr),
AMIPtr_(nullptr),
AMIReverse_(dict.getOrDefault("flipNormals", false)), AMIReverse_(dict.getOrDefault("flipNormals", false)),
AMIPtr_
(
AMIInterpolation::New
(
dict.lookupOrDefault("AMIMethod", faceAreaWeightAMI::typeName),
dict,
AMIReverse_
)
),
surfPtr_(nullptr), surfPtr_(nullptr),
surfDict_(dict.subOrEmptyDict("surface")) surfDict_(dict.subOrEmptyDict("surface"))
{ {
@ -1089,8 +1088,8 @@ Foam::mappedPatchBase::mappedPatchBase
distance_(mpb.distance_), distance_(mpb.distance_),
sameRegion_(mpb.sameRegion_), sameRegion_(mpb.sameRegion_),
mapPtr_(nullptr), mapPtr_(nullptr),
AMIPtr_(nullptr),
AMIReverse_(mpb.AMIReverse_), AMIReverse_(mpb.AMIReverse_),
AMIPtr_(mpb.AMIPtr_->clone()),
surfPtr_(nullptr), surfPtr_(nullptr),
surfDict_(mpb.surfDict_) surfDict_(mpb.surfDict_)
{} {}
@ -1119,8 +1118,8 @@ Foam::mappedPatchBase::mappedPatchBase
distance_(mpb.distance_), distance_(mpb.distance_),
sameRegion_(mpb.sameRegion_), sameRegion_(mpb.sameRegion_),
mapPtr_(nullptr), mapPtr_(nullptr),
AMIPtr_(nullptr),
AMIReverse_(mpb.AMIReverse_), AMIReverse_(mpb.AMIReverse_),
AMIPtr_(mpb.AMIPtr_->clone()),
surfPtr_(nullptr), surfPtr_(nullptr),
surfDict_(mpb.surfDict_) surfDict_(mpb.surfDict_)
{} {}
@ -1137,8 +1136,8 @@ Foam::mappedPatchBase::~mappedPatchBase()
void Foam::mappedPatchBase::clearOut() void Foam::mappedPatchBase::clearOut()
{ {
mapPtr_.clear(); mapPtr_.clear();
AMIPtr_.clear();
surfPtr_.clear(); surfPtr_.clear();
AMIPtr_->upToDate() = false;
} }

View File

@ -231,12 +231,12 @@ protected:
// AMI interpolator (only for NEARESTPATCHFACEAMI) // AMI interpolator (only for NEARESTPATCHFACEAMI)
//- Pointer to AMI interpolator
mutable autoPtr<AMIPatchToPatchInterpolation> AMIPtr_;
//- Flag to indicate that slave patch should be reversed for AMI //- Flag to indicate that slave patch should be reversed for AMI
const bool AMIReverse_; const bool AMIReverse_;
//- Pointer to AMI interpolator
mutable autoPtr<AMIPatchToPatchInterpolation> AMIPtr_;
//- Pointer to projection surface employed by AMI interpolator //- Pointer to projection surface employed by AMI interpolator
mutable autoPtr<searchableSurface> surfPtr_; mutable autoPtr<searchableSurface> surfPtr_;