/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019-2025 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 .
\*---------------------------------------------------------------------------*/
#include "calculatedProcessorFvPatchField.H"
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
template
Foam::calculatedProcessorFvPatchField::calculatedProcessorFvPatchField
(
const lduInterface& interface,
const fvPatch& p,
const DimensionedField& iF
)
:
coupledFvPatchField(p, iF),
procInterface_(refCast(interface)),
sendRequest_(-1),
recvRequest_(-1)
{}
template
Foam::calculatedProcessorFvPatchField::calculatedProcessorFvPatchField
(
const calculatedProcessorFvPatchField& ptf
)
:
coupledFvPatchField(ptf),
procInterface_(ptf.procInterface_),
sendRequest_(-1),
recvRequest_(-1)
{}
template
Foam::calculatedProcessorFvPatchField::calculatedProcessorFvPatchField
(
const calculatedProcessorFvPatchField& ptf,
const DimensionedField& iF
)
:
coupledFvPatchField(ptf, iF),
procInterface_(ptf.procInterface_),
sendRequest_(-1),
recvRequest_(-1)
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template
bool Foam::calculatedProcessorFvPatchField::all_ready() const
{
return UPstream::finishedRequestPair(recvRequest_, sendRequest_);
}
template
bool Foam::calculatedProcessorFvPatchField::ready() const
{
const bool ok = UPstream::finishedRequest(recvRequest_);
if (ok)
{
recvRequest_ = -1;
if (UPstream::finishedRequest(sendRequest_)) sendRequest_ = -1;
}
return ok;
}
template
Foam::tmp>
Foam::calculatedProcessorFvPatchField::patchNeighbourField() const
{
if (!this->ready())
{
FatalErrorInFunction
<< "Outstanding request on patch of size "
<< procInterface_.faceCells().size()
<< " between proc " << procInterface_.myProcNo()
<< " and " << procInterface_.neighbProcNo()
<< abort(FatalError);
}
return *this;
}
template
void Foam::calculatedProcessorFvPatchField::patchNeighbourField
(
UList& pnf
) const
{
if (!this->ready())
{
FatalErrorInFunction
<< "Outstanding request on patch of size "
<< procInterface_.faceCells().size()
<< " between proc " << procInterface_.myProcNo()
<< " and " << procInterface_.neighbProcNo()
<< abort(FatalError);
}
pnf.deepCopy(*this);
}
template
void Foam::calculatedProcessorFvPatchField::initEvaluate
(
const Pstream::commsTypes commsType
)
{
if (UPstream::parRun())
{
if constexpr (!is_contiguous_v)
{
FatalErrorInFunction
<< "Invalid for non-contiguous data types"
<< abort(FatalError);
}
// Bypass patchInternalField since uses fvPatch addressing
Field& self = *this; // Receive straight into *this
{
const Field& psiInternal = this->internalField();
const labelUList& faceCells = procInterface_.faceCells();
sendBuf_.resize_nocopy(faceCells.size());
self.resize_nocopy(faceCells.size());
forAll(faceCells, i)
{
sendBuf_[i] = psiInternal[faceCells[i]];
}
}
recvRequest_ = UPstream::nRequests();
UIPstream::read
(
UPstream::commsTypes::nonBlocking,
procInterface_.neighbProcNo(),
self,
procInterface_.tag(),
procInterface_.comm()
);
sendRequest_ = UPstream::nRequests();
UOPstream::write
(
UPstream::commsTypes::nonBlocking,
procInterface_.neighbProcNo(),
sendBuf_,
procInterface_.tag(),
procInterface_.comm()
);
}
}
template
void Foam::calculatedProcessorFvPatchField::evaluate
(
const Pstream::commsTypes commsType
)
{
if (UPstream::parRun())
{
// Require receive data.
// Only update the send request state.
UPstream::waitRequest(recvRequest_); recvRequest_ = -1;
if (UPstream::finishedRequest(sendRequest_)) sendRequest_ = -1;
}
}
template
void Foam::calculatedProcessorFvPatchField::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->all_ready())
{
FatalErrorInFunction
<< "Outstanding request(s) on interface "
//<< interface_.name()
<< abort(FatalError);
}
// Bypass patchInternalField since uses fvPatch addressing
const labelUList& faceCells = lduAddr.patchAddr(patchId);
{
scalarSendBuf_.resize_nocopy(faceCells.size());
scalarRecvBuf_.resize_nocopy(faceCells.size());
forAll(faceCells, i)
{
scalarSendBuf_[i] = psiInternal[faceCells[i]];
}
}
recvRequest_ = UPstream::nRequests();
UIPstream::read
(
UPstream::commsTypes::nonBlocking,
procInterface_.neighbProcNo(),
scalarRecvBuf_,
procInterface_.tag(),
procInterface_.comm()
);
sendRequest_ = UPstream::nRequests();
UOPstream::write
(
UPstream::commsTypes::nonBlocking,
procInterface_.neighbProcNo(),
scalarSendBuf_,
procInterface_.tag(),
procInterface_.comm()
);
this->updatedMatrix(false);
}
template
void Foam::calculatedProcessorFvPatchField::addToInternalField
(
solveScalarField& result,
const bool add,
const scalarField& coeffs,
const solveScalarField& vals
) const
{
const labelUList& faceCells = this->procInterface_.faceCells();
if (add)
{
forAll(faceCells, elemI)
{
result[faceCells[elemI]] += coeffs[elemI]*vals[elemI];
}
}
else
{
forAll(faceCells, elemI)
{
result[faceCells[elemI]] -= coeffs[elemI]*vals[elemI];
}
}
}
template
void Foam::calculatedProcessorFvPatchField::updateInterfaceMatrix
(
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->updatedMatrix())
{
return;
}
if (UPstream::parRun())
{
// Require receive data.
// Only update the send request state.
UPstream::waitRequest(recvRequest_); recvRequest_ = -1;
if (UPstream::finishedRequest(sendRequest_)) sendRequest_ = -1;
}
// Consume straight from receive buffer. Note use of our own
// helper to avoid using fvPatch addressing
addToInternalField(result, !add, coeffs, scalarRecvBuf_);
this->updatedMatrix(true);
}
// ************************************************************************* //