mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: cyclicACMI: add non-blocking matrix updates.
This commit is contained in:
committed by
Andrew Heather
parent
7c8daed124
commit
7c64cdbd01
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -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
|
||||
(
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user