ENH: cyclicACMI: add non-blocking matrix updates.

This commit is contained in:
Mattijs Janssens
2023-11-27 13:58:02 +00:00
committed by Andrew Heather
parent 7c8daed124
commit 7c64cdbd01
5 changed files with 688 additions and 66 deletions

View File

@ -41,7 +41,10 @@ Foam::cyclicACMIFvPatchField<Type>::cyclicACMIFvPatchField
:
cyclicACMILduInterfaceField(),
coupledFvPatchField<Type>(p, iF),
cyclicACMIPatch_(refCast<const cyclicACMIFvPatch>(p))
cyclicACMIPatch_(refCast<const cyclicACMIFvPatch>(p)),
sendRequests_(0),
recvRequests_(0),
patchNeighbourFieldPtr_(nullptr)
{}
@ -55,7 +58,10 @@ Foam::cyclicACMIFvPatchField<Type>::cyclicACMIFvPatchField
:
cyclicACMILduInterfaceField(),
coupledFvPatchField<Type>(p, iF, dict, IOobjectOption::NO_READ),
cyclicACMIPatch_(refCast<const cyclicACMIFvPatch>(p, dict))
cyclicACMIPatch_(refCast<const cyclicACMIFvPatch>(p, dict)),
sendRequests_(0),
recvRequests_(0),
patchNeighbourFieldPtr_(nullptr)
{
if (!isA<cyclicACMIFvPatch>(p))
{
@ -68,6 +74,21 @@ Foam::cyclicACMIFvPatchField<Type>::cyclicACMIFvPatchField
<< exit(FatalIOError);
}
if (cacheNeighbourField())
{
// Handle neighbour value first, before any evaluate()
const auto* hasNeighbValue =
dict.findEntry("neighbourValue", keyType::LITERAL);
if (hasNeighbValue)
{
patchNeighbourFieldPtr_.reset
(
new Field<Type>(*hasNeighbValue, p.size())
);
}
}
// Use 'value' supplied, or set to coupled field
if (!this->readValueEntry(dict) && this->coupled())
{
@ -108,8 +129,19 @@ Foam::cyclicACMIFvPatchField<Type>::cyclicACMIFvPatchField
:
cyclicACMILduInterfaceField(),
coupledFvPatchField<Type>(ptf, p, iF, mapper),
cyclicACMIPatch_(refCast<const cyclicACMIFvPatch>(p))
cyclicACMIPatch_(refCast<const cyclicACMIFvPatch>(p)),
sendRequests_(0),
recvRequests_(0),
patchNeighbourFieldPtr_(nullptr)
{
if (ptf.patchNeighbourFieldPtr_ && cacheNeighbourField())
{
patchNeighbourFieldPtr_.reset
(
new Field<Type>(ptf.patchNeighbourFieldPtr_(), mapper)
);
}
if (!isA<cyclicACMIFvPatch>(this->patch()))
{
FatalErrorInFunction
@ -120,10 +152,15 @@ Foam::cyclicACMIFvPatchField<Type>::cyclicACMIFvPatchField
<< " in file " << this->internalField().objectPath()
<< exit(FatalError);
}
if (debug && !ptf.all_ready())
{
FatalErrorInFunction
<< "Outstanding request(s) on patch " << cyclicACMIPatch_.name()
<< abort(FatalError);
}
}
template<class Type>
Foam::cyclicACMIFvPatchField<Type>::cyclicACMIFvPatchField
(
@ -132,8 +169,18 @@ Foam::cyclicACMIFvPatchField<Type>::cyclicACMIFvPatchField
:
cyclicACMILduInterfaceField(),
coupledFvPatchField<Type>(ptf),
cyclicACMIPatch_(ptf.cyclicACMIPatch_)
{}
cyclicACMIPatch_(ptf.cyclicACMIPatch_),
sendRequests_(0),
recvRequests_(0),
patchNeighbourFieldPtr_(ptf.patchNeighbourFieldPtr_)
{
if (debug && !ptf.all_ready())
{
FatalErrorInFunction
<< "Outstanding request(s) on patch " << cyclicACMIPatch_.name()
<< abort(FatalError);
}
}
template<class Type>
@ -145,8 +192,18 @@ Foam::cyclicACMIFvPatchField<Type>::cyclicACMIFvPatchField
:
cyclicACMILduInterfaceField(),
coupledFvPatchField<Type>(ptf, iF),
cyclicACMIPatch_(ptf.cyclicACMIPatch_)
{}
cyclicACMIPatch_(ptf.cyclicACMIPatch_),
sendRequests_(0),
recvRequests_(0),
patchNeighbourFieldPtr_(nullptr)
{
if (debug && !ptf.all_ready())
{
FatalErrorInFunction
<< "Outstanding request(s) on patch " << cyclicACMIPatch_.name()
<< abort(FatalError);
}
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
@ -159,13 +216,87 @@ bool Foam::cyclicACMIFvPatchField<Type>::coupled() const
template<class Type>
Foam::tmp<Foam::Field<Type>>
Foam::cyclicACMIFvPatchField<Type>::patchNeighbourField() const
bool Foam::cyclicACMIFvPatchField<Type>::all_ready() const
{
const Field<Type>& iField = this->primitiveField();
//const cyclicACMIPolyPatch& cpp = cyclicACMIPatch_.cyclicACMIPatch();
int done = 0;
// By pass polyPatch to get nbrId. Instead use cyclicAMIFvPatch virtual
if
(
UPstream::finishedRequests
(
recvRequests_.start(),
recvRequests_.size()
)
)
{
recvRequests_.clear();
++done;
}
if
(
UPstream::finishedRequests
(
sendRequests_.start(),
sendRequests_.size()
)
)
{
sendRequests_.clear();
++done;
}
return (done == 2);
}
template<class Type>
bool Foam::cyclicACMIFvPatchField<Type>::ready() const
{
if
(
UPstream::finishedRequests
(
recvRequests_.start(),
recvRequests_.size()
)
)
{
recvRequests_.clear();
if
(
UPstream::finishedRequests
(
sendRequests_.start(),
sendRequests_.size()
)
)
{
sendRequests_.clear();
}
return true;
}
return false;
}
template<class Type>
Foam::tmp<Foam::Field<Type>>
Foam::cyclicACMIFvPatchField<Type>::patchNeighbourField
(
const Field<Type>& iField
) const
{
DebugPout
<< "cyclicACMIFvPatchField::patchNeighbourField(const Field<Type>&) :"
<< " field:" << this->internalField().name()
<< " patch:" << this->patch().name()
<< endl;
// By pass polyPatch to get nbrId. Instead use cyclicACMIFvPatch virtual
// neighbPatch()
const cyclicACMIFvPatch& neighbPatch = cyclicACMIPatch_.neighbPatch();
const labelUList& nbrFaceCells = neighbPatch.faceCells();
@ -192,6 +323,77 @@ Foam::cyclicACMIFvPatchField<Type>::patchNeighbourField() const
}
template<class Type>
bool Foam::cyclicACMIFvPatchField<Type>::cacheNeighbourField()
{
/*
return
(
GeometricField<Type, fvPatchField, volMesh>::Boundary::localConsistency
!= 0
);
*/
return false;
}
template<class Type>
Foam::tmp<Foam::Field<Type>>
Foam::cyclicACMIFvPatchField<Type>::patchNeighbourField() const
{
if (this->ownerAMI().distributed() && cacheNeighbourField())
{
if (!this->ready())
{
FatalErrorInFunction
<< "Outstanding recv request(s) on patch "
<< cyclicACMIPatch_.name()
<< " field " << this->internalField().name()
<< abort(FatalError);
}
// Initialise if not done in construct-from-dictionary
if (!patchNeighbourFieldPtr_)
{
DebugPout
<< "cyclicACMIFvPatchField::patchNeighbourField() :"
<< " field:" << this->internalField().name()
<< " patch:" << this->patch().name()
<< " calculating&caching patchNeighbourField"
<< endl;
// Do interpolation and store result
patchNeighbourFieldPtr_.reset
(
patchNeighbourField(this->primitiveField()).ptr()
);
}
else
{
DebugPout
<< "cyclicACMIFvPatchField::patchNeighbourField() :"
<< " field:" << this->internalField().name()
<< " patch:" << this->patch().name()
<< " returning cached patchNeighbourField"
<< endl;
}
return patchNeighbourFieldPtr_();
}
else
{
// Do interpolation
DebugPout
<< "cyclicACMIFvPatchField::evaluate() :"
<< " field:" << this->internalField().name()
<< " patch:" << this->patch().name()
<< " calculating up-to-date patchNeighbourField"
<< endl;
return patchNeighbourField(this->primitiveField());
}
}
template<class Type>
const Foam::cyclicACMIFvPatchField<Type>&
Foam::cyclicACMIFvPatchField<Type>::neighbourPatchField() const
@ -224,6 +426,178 @@ Foam::cyclicACMIFvPatchField<Type>::nonOverlapPatchField() const
}
template<class Type>
void Foam::cyclicACMIFvPatchField<Type>::initEvaluate
(
const Pstream::commsTypes commsType
)
{
if (!this->updated())
{
this->updateCoeffs();
}
if (this->ownerAMI().distributed() && cacheNeighbourField())
{
if (commsType != UPstream::commsTypes::nonBlocking)
{
// Invalidate old field - or flag as fatal?
patchNeighbourFieldPtr_.reset(nullptr);
return;
}
// Start sending
DebugPout
<< "cyclicACMIFvPatchField::initEvaluate() :"
<< " field:" << this->internalField().name()
<< " patch:" << this->patch().name()
<< " starting send&receive"
<< endl;
if (!this->ready())
{
FatalErrorInFunction
<< "Outstanding recv request(s) on patch "
<< cyclicACMIPatch_.name()
<< " field " << this->internalField().name()
<< abort(FatalError);
}
// By-pass polyPatch to get nbrId. Instead use cyclicACMIFvPatch virtual
// neighbPatch()
const cyclicACMIFvPatch& neighbPatch = cyclicACMIPatch_.neighbPatch();
const labelUList& nbrFaceCells = neighbPatch.faceCells();
const Field<Type> pnf(this->primitiveField(), nbrFaceCells);
cyclicACMIPatch_.initInterpolate
(
pnf,
sendRequests_,
sendBufs_,
recvRequests_,
recvBufs_
);
}
}
template<class Type>
void Foam::cyclicACMIFvPatchField<Type>::evaluate
(
const Pstream::commsTypes commsType
)
{
if (!this->updated())
{
this->updateCoeffs();
}
const auto& AMI = this->ownerAMI();
if (AMI.distributed() && cacheNeighbourField())
{
// Calculate patchNeighbourField
if (commsType != UPstream::commsTypes::nonBlocking)
{
FatalErrorInFunction
<< "Can only evaluate distributed AMI with nonBlocking"
<< exit(FatalError);
}
patchNeighbourFieldPtr_.reset(nullptr);
if (!this->ready())
{
FatalErrorInFunction
<< "Outstanding recv request(s) on patch "
<< cyclicACMIPatch_.name()
<< " field " << this->internalField().name()
<< abort(FatalError);
}
patchNeighbourFieldPtr_.reset
(
cyclicACMIPatch_.interpolate
(
Field<Type>::null(), // Not used for distributed
recvRequests_,
recvBufs_
).ptr()
);
auto& patchNeighbourField = patchNeighbourFieldPtr_.ref();
if (doTransform())
{
// In-place transform
transform(patchNeighbourField, forwardT(), patchNeighbourField);
}
}
// Use patchNeighbourField() and patchInternalField() to obtain face value
coupledFvPatchField<Type>::evaluate(commsType);
}
template<class Type>
void Foam::cyclicACMIFvPatchField<Type>::initInterfaceMatrixUpdate
(
solveScalarField& result,
const bool add,
const lduAddressing& lduAddr,
const label patchId,
const solveScalarField& psiInternal,
const scalarField& coeffs,
const direction cmpt,
const Pstream::commsTypes commsType
) const
{
if (this->ownerAMI().distributed())
{
// Start sending
if (commsType != UPstream::commsTypes::nonBlocking)
{
FatalErrorInFunction
<< "Can only evaluate distributed AMI with nonBlocking"
<< exit(FatalError);
}
DebugPout
<< "cyclicACMIFvPatchField::initInterfaceMatrixUpdate() :"
<< " field:" << this->internalField().name()
<< " patch:" << this->patch().name()
<< " starting send&receive"
<< endl;
if (!this->ready())
{
FatalErrorInFunction
<< "Outstanding recv request(s) on patch "
<< cyclicACMIPatch_.name()
<< " field " << this->internalField().name()
<< abort(FatalError);
}
const labelUList& nbrFaceCells =
lduAddr.patchAddr(cyclicACMIPatch_.neighbPatchID());
solveScalarField pnf(psiInternal, nbrFaceCells);
// Transform according to the transformation tensors
transformCoupleField(pnf, cmpt);
cyclicACMIPatch_.initInterpolate
(
pnf,
sendRequests_,
scalarSendBufs_,
recvRequests_,
scalarRecvBufs_
);
}
}
template<class Type>
void Foam::cyclicACMIFvPatchField<Type>::updateInterfaceMatrix
(
@ -234,33 +608,113 @@ void Foam::cyclicACMIFvPatchField<Type>::updateInterfaceMatrix
const solveScalarField& psiInternal,
const scalarField& coeffs,
const direction cmpt,
const Pstream::commsTypes
const Pstream::commsTypes commsType
) const
{
DebugPout<< "cyclicACMIFvPatchField::updateInterfaceMatrix() :"
<< " field:" << this->internalField().name()
<< " patch:" << this->patch().name()
<< endl;
// note: only applying coupled contribution
// const labelUList& nbrFaceCellsCoupled =
// lduAddr.patchAddr
// (
// cyclicACMIPatch_.cyclicACMIPatch().neighbPatchID()
// );
const labelUList& nbrFaceCellsCoupled =
lduAddr.patchAddr(cyclicACMIPatch_.neighbPatchID());
solveScalarField pnf(psiInternal, nbrFaceCellsCoupled);
// Transform according to the transformation tensors
transformCoupleField(pnf, cmpt);
pnf = cyclicACMIPatch_.interpolate(pnf);
const labelUList& faceCells = lduAddr.patchAddr(patchId);
solveScalarField pnf;
if (this->ownerAMI().distributed())
{
if (commsType != UPstream::commsTypes::nonBlocking)
{
FatalErrorInFunction
<< "Can only evaluate distributed AMI with nonBlocking"
<< exit(FatalError);
}
DebugPout
<< "cyclicACMIFvPatchField::evaluate() :"
<< " field:" << this->internalField().name()
<< " patch:" << this->patch().name()
<< " consuming received coupled neighbourfield"
<< endl;
pnf =
cyclicACMIPatch_.interpolate
(
solveScalarField::null(), // Not used for distributed
recvRequests_,
scalarRecvBufs_
);
}
else
{
const labelUList& nbrFaceCells =
lduAddr.patchAddr(cyclicACMIPatch_.neighbPatchID());
pnf = solveScalarField(psiInternal, nbrFaceCells);
// Transform according to the transformation tensors
transformCoupleField(pnf, cmpt);
pnf = cyclicACMIPatch_.interpolate(pnf);
}
this->addToInternalField(result, !add, faceCells, coeffs, pnf);
}
template<class Type>
void Foam::cyclicACMIFvPatchField<Type>::initInterfaceMatrixUpdate
(
Field<Type>& result,
const bool add,
const lduAddressing& lduAddr,
const label patchId,
const Field<Type>& psiInternal,
const scalarField& coeffs,
const Pstream::commsTypes commsType
) const
{
const auto& AMI = this->ownerAMI();
if (AMI.distributed())
{
if (commsType != UPstream::commsTypes::nonBlocking)
{
FatalErrorInFunction
<< "Can only evaluate distributed AMI with nonBlocking"
<< exit(FatalError);
}
if (!this->ready())
{
FatalErrorInFunction
<< "Outstanding recv request(s) on patch "
<< cyclicACMIPatch_.name()
<< " field " << this->internalField().name()
<< abort(FatalError);
}
const labelUList& nbrFaceCells =
lduAddr.patchAddr(cyclicACMIPatch_.neighbPatchID());
Field<Type> pnf(psiInternal, nbrFaceCells);
// Transform according to the transformation tensors
transformCoupleField(pnf);
cyclicACMIPatch_.initInterpolate
(
pnf,
sendRequests_,
sendBufs_,
recvRequests_,
recvBufs_
);
}
}
template<class Type>
void Foam::cyclicACMIFvPatchField<Type>::updateInterfaceMatrix
(
@ -270,23 +724,47 @@ void Foam::cyclicACMIFvPatchField<Type>::updateInterfaceMatrix
const label patchId,
const Field<Type>& psiInternal,
const scalarField& coeffs,
const Pstream::commsTypes
const Pstream::commsTypes commsType
) const
{
// note: only applying coupled contribution
const labelUList& nbrFaceCellsCoupled =
lduAddr.patchAddr(cyclicACMIPatch_.neighbPatchID());
Field<Type> pnf(psiInternal, nbrFaceCellsCoupled);
// Transform according to the transformation tensors
transformCoupleField(pnf);
pnf = cyclicACMIPatch_.interpolate(pnf);
const labelUList& faceCells = lduAddr.patchAddr(patchId);
const auto& AMI = this->ownerAMI();
Field<Type> pnf;
if (AMI.distributed())
{
if (commsType != UPstream::commsTypes::nonBlocking)
{
FatalErrorInFunction
<< "Can only evaluate distributed AMI with nonBlocking"
<< exit(FatalError);
}
pnf =
cyclicACMIPatch_.interpolate
(
Field<Type>::null(), // Not used for distributed
recvRequests_,
recvBufs_
);
}
else
{
const labelUList& nbrFaceCells =
lduAddr.patchAddr(cyclicACMIPatch_.neighbPatchID());
pnf = Field<Type>(psiInternal, nbrFaceCells);
// Transform according to the transformation tensors
transformCoupleField(pnf);
pnf = cyclicACMIPatch_.interpolate(pnf);
}
this->addToInternalField(result, !add, faceCells, coeffs, pnf);
}
@ -364,7 +842,7 @@ void Foam::cyclicACMIFvPatchField<Type>::manipulateMatrix
}
// Set internalCoeffs and boundaryCoeffs in the assembly matrix
// on clyclicAMI patches to be used in the individual matrix by
// on cyclicACMI patches to be used in the individual matrix by
// matrix.flux()
if (matrix.psi(mat).mesh().fluxRequired(this->internalField().name()))
{
@ -462,6 +940,11 @@ void Foam::cyclicACMIFvPatchField<Type>::write(Ostream& os) const
{
fvPatchField<Type>::write(os);
fvPatchField<Type>::writeValueEntry(os);
if (patchNeighbourFieldPtr_)
{
patchNeighbourFieldPtr_->writeEntry("neighbourValue", os);
}
}

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2013-2016 OpenFOAM Foundation
Copyright (C) 2019 OpenCFD Ltd.
Copyright (C) 2019,2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -41,6 +41,8 @@ Usage
<patchName>
{
type cyclicACMI;
value <initial value>;
neighbourValue <initial value of neighbour patch cells>;
}
\endverbatim
@ -80,8 +82,52 @@ class cyclicACMIFvPatchField
const cyclicACMIFvPatch& cyclicACMIPatch_;
// Sending and receiving (distributed AMI)
//- Current range of send requests (non-blocking)
mutable labelRange sendRequests_;
//- Current range of recv requests (non-blocking)
mutable labelRange recvRequests_;
//- Send buffers
mutable PtrList<List<Type>> sendBufs_;
//- Receive buffers_
mutable PtrList<List<Type>> recvBufs_;
//- Scalar send buffers
mutable PtrList<List<solveScalar>> scalarSendBufs_;
//- Scalar receive buffers
mutable PtrList<List<solveScalar>> scalarRecvBufs_;
//- Neighbour coupled internal cell data
mutable autoPtr<Field<Type>> patchNeighbourFieldPtr_;
// Private Member Functions
//- Return the AMI corresponding to the owner side
const AMIPatchToPatchInterpolation& ownerAMI() const
{
return
(
cyclicACMIPatch_.owner()
? cyclicACMIPatch_.AMI()
: cyclicACMIPatch_.neighbPatch().AMI()
);
}
//- All receive/send requests have completed
virtual bool all_ready() const;
//- Use neighbour field caching
static bool cacheNeighbourField();
//- Return neighbour coupled internal cell data
tmp<Field<Type>> patchNeighbourField(const Field<Type>&) const;
//- Return neighbour side field given internal fields
template<class Type2>
tmp<Field<Type2>> neighbourSideField
@ -174,12 +220,15 @@ public:
}
// Evaluation functions
// Coupling
//- Return true if coupled. Note that the underlying patch
// is not coupled() - the points don't align
virtual bool coupled() const;
//- Are all (receive) data available?
virtual bool ready() const;
//- Return true if this patch field fixes a value
// Needed to check if a level has to be specified while solving
// Poisson equations
@ -200,7 +249,6 @@ public:
}
}
//- Return neighbour coupled internal cell data
virtual tmp<Field<Type>> patchNeighbourField() const;
@ -210,7 +258,32 @@ public:
//- Return reference to non-overlapping patchField
const fvPatchField<Type>& nonOverlapPatchField() const;
//- Update result field based on interface functionality
// Evaluation
//- Initialise the evaluation of the patch field
virtual void initEvaluate(const Pstream::commsTypes commsType);
//- Evaluate the patch field
virtual void evaluate(const Pstream::commsTypes commsType);
// Coupled interface functionality
//- Initialise neighbour matrix update
virtual void initInterfaceMatrixUpdate
(
solveScalarField& result,
const bool add,
const lduAddressing& lduAddr,
const label patchId,
const solveScalarField& psiInternal,
const scalarField& coeffs,
const direction cmpt,
const Pstream::commsTypes commsType
) const;
//- Update result field based on interface functionality
virtual void updateInterfaceMatrix
(
solveScalarField& result,
@ -223,6 +296,18 @@ public:
const Pstream::commsTypes commsType
) const;
//- Initialise neighbour matrix update
virtual void initInterfaceMatrixUpdate
(
Field<Type>& result,
const bool add,
const lduAddressing& lduAddr,
const label patchId,
const Field<Type>& psiInternal,
const scalarField& coeffs,
const Pstream::commsTypes commsType
) const;
//- Update result field based on interface functionality
virtual void updateInterfaceMatrix
(

View File

@ -76,16 +76,19 @@ Foam::cyclicAMIFvPatchField<Type>::cyclicAMIFvPatchField
<< exit(FatalIOError);
}
// Handle neighbour value first, before any evaluate()
const auto* hasNeighbValue =
dict.findEntry("neighbourValue", keyType::LITERAL);
if (hasNeighbValue)
if (cacheNeighbourField())
{
patchNeighbourFieldPtr_.reset
(
new Field<Type>(*hasNeighbValue, p.size())
);
// Handle neighbour value first, before any evaluate()
const auto* hasNeighbValue =
dict.findEntry("neighbourValue", keyType::LITERAL);
if (hasNeighbValue)
{
patchNeighbourFieldPtr_.reset
(
new Field<Type>(*hasNeighbValue, p.size())
);
}
}
// Use 'value' supplied, or evaluate (if coupled) or set to internal field
@ -119,7 +122,7 @@ Foam::cyclicAMIFvPatchField<Type>::cyclicAMIFvPatchField
recvRequests_(0),
patchNeighbourFieldPtr_(nullptr)
{
if (ptf.patchNeighbourFieldPtr_)
if (ptf.patchNeighbourFieldPtr_ && cacheNeighbourField())
{
patchNeighbourFieldPtr_.reset
(
@ -298,11 +301,22 @@ Foam::cyclicAMIFvPatchField<Type>::patchNeighbourField
}
template<class Type>
bool Foam::cyclicAMIFvPatchField<Type>::cacheNeighbourField()
{
return
(
GeometricField<Type, fvPatchField, volMesh>::Boundary::localConsistency
!= 0
);
}
template<class Type>
Foam::tmp<Foam::Field<Type>>
Foam::cyclicAMIFvPatchField<Type>::patchNeighbourField() const
{
if (this->ownerAMI().distributed())
if (this->ownerAMI().distributed() && cacheNeighbourField())
{
if (!this->ready())
{
@ -360,7 +374,7 @@ void Foam::cyclicAMIFvPatchField<Type>::initEvaluate
this->updateCoeffs();
}
if (this->ownerAMI().distributed())
if (this->ownerAMI().distributed() && cacheNeighbourField())
{
if (commsType != UPstream::commsTypes::nonBlocking)
{
@ -404,7 +418,7 @@ void Foam::cyclicAMIFvPatchField<Type>::evaluate
const auto& AMI = this->ownerAMI();
if (AMI.distributed())
if (AMI.distributed() && cacheNeighbourField())
{
// Calculate patchNeighbourField
if (commsType != UPstream::commsTypes::nonBlocking)
@ -513,16 +527,11 @@ void Foam::cyclicAMIFvPatchField<Type>::updateInterfaceMatrix
const labelUList& faceCells = lduAddr.patchAddr(patchId);
const auto& AMI =
(
cyclicAMIPatch_.owner()
? cyclicAMIPatch_.AMI()
: cyclicAMIPatch_.neighbPatch().AMI()
);
const auto& AMI = this->ownerAMI();
solveScalarField pnf;
if (this->ownerAMI().distributed())
if (AMI.distributed())
{
if (commsType != UPstream::commsTypes::nonBlocking)
{

View File

@ -133,6 +133,9 @@ class cyclicAMIFvPatchField
//- All receive/send requests have completed
virtual bool all_ready() const;
//- Use neighbour field caching
static bool cacheNeighbourField();
//- Return neighbour coupled internal cell data
tmp<Field<Type>> patchNeighbourField(const Field<Type>&) const;

View File

@ -213,6 +213,48 @@ public:
return interpolate(tfld());
}
// Interpolations (non-blocking). Subject to change
template<class Type>
void initInterpolate
(
const Field<Type>& fld,
labelRange& sendRequests,
PtrList<List<Type>>& sendBuffers,
labelRange& recvRequests,
PtrList<List<Type>>& recvBuffers
) const
{
// Make sure areas are up-to-date
updateAreas();
cyclicACMIPolyPatch_.initInterpolate
(
fld,
sendRequests,
sendBuffers,
recvRequests,
recvBuffers
);
}
template<class Type>
tmp<Field<Type>> interpolate
(
const Field<Type>& localFld,
const labelRange& requests, // The receive requests
const PtrList<List<Type>>& recvBuffers
) const
{
return cyclicACMIPolyPatch_.interpolate
(
localFld,
requests,
recvBuffers,
UList<Type>()
);
}
// Interface transfer functions