openfoam/src/meshTools/AMIInterpolation/patches/cyclicAMI/cyclicAMIPolyPatch/cyclicAMIPolyPatchTemplates.C
mattijs 69169c5abe ENH: add non-blocking handling for cyclicAMI (#2963)
Co-authored-by: Mark Olesen <>
2023-08-30 13:39:16 +00:00

411 lines
11 KiB
C

/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2021-2023 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/>.
\*---------------------------------------------------------------------------*/
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
template<class Type>
Foam::tmp<Foam::Field<Type>> Foam::cyclicAMIPolyPatch::interpolateUntransformed
(
const Field<Type>& fld,
const UList<Type>& defaultValues
) const
{
if (owner())
{
return AMI().interpolateToSource(fld, defaultValues);
}
else
{
return neighbPatch().AMI().interpolateToTarget(fld, defaultValues);
}
}
template<class Type>
Foam::tmp<Foam::Field<Type>> Foam::cyclicAMIPolyPatch::interpolate
(
const Field<Type>& fld,
const UList<Type>& defaultValues
) const
{
autoPtr<coordSystem::cylindrical> cs;
// Similar to doTransform.
// - could also check if !std::is_same<sphericalTensor, Type>:value
if (is_vectorspace<Type>::value)
{
cs.reset(cylindricalCS());
}
if (!cs)
{
return interpolateUntransformed(fld, defaultValues);
}
else
{
const cyclicAMIPolyPatch& nbrPp = this->neighbPatch();
if (debug)
{
Pout<< "cyclicAMIPolyPatch::interpolate :"
<< " patch:" << this->name()
<< " size:" << this->size()
<< " nbrPatch:" << nbrPp.name()
<< " size:" << nbrPp.size()
<< endl;
}
if (fld.size() != nbrPp.size())
{
FatalErrorInFunction
<< "Patch:" << this->name()
<< " size:" << this->size()
<< " neighbour patch:" << nbrPp.name()
<< " size:" << nbrPp.size()
<< " fld size:" << fld.size()
<< exit(FatalError);
}
Field<Type> localFld(fld.size());
// Transform to cylindrical coords
{
const tensorField nbrT(cs().R(nbrPp.faceCentres()));
Foam::invTransform(localFld, nbrT, fld);
}
if (debug&2)
{
const vectorField::subField nbrFc(nbrPp.faceCentres());
Pout<< "On patch:" << this->name()
<< " size:" << this->size()
<< " fc:" << gAverage(this->faceCentres())
<< " getting remote data from:" << nbrPp.name()
<< " size:" << nbrPp.size()
<< " fc:" << gAverage(nbrFc)
<< endl;
forAll(fld, i)
{
Pout<< "At:" << nbrFc[i] << nl
<< " cart:" << fld[i] << nl
<< " cyli:" << localFld[i] << nl
<< endl;
}
}
const tensorField ownT(cs().R(this->faceCentres()));
Field<Type> localDeflt(defaultValues.size());
if (defaultValues.size() == size())
{
// Transform default values into cylindrical coords (using
// *this faceCentres)
// We get in UList (why? Copied from cyclicAMI). Convert to
// Field so we can use transformField routines.
const SubField<Type> defaultSubFld(defaultValues);
const Field<Type>& defaultFld(defaultSubFld);
Foam::invTransform(localDeflt, ownT, defaultFld);
}
// Do the actual interpolation and interpolate back to cartesian
return Foam::transform
(
ownT,
interpolateUntransformed(localFld, localDeflt)
);
}
}
template<class Type>
Foam::tmp<Foam::Field<Type>> Foam::cyclicAMIPolyPatch::interpolate
(
const tmp<Field<Type>>& tFld,
const UList<Type>& defaultValues
) const
{
return interpolate(tFld(), defaultValues);
}
template<class Type>
void Foam::cyclicAMIPolyPatch::initInterpolateUntransformed
(
const Field<Type>& fld,
labelRange& sendRequests,
PtrList<List<Type>>& sendBuffers,
labelRange& recvRequests,
PtrList<List<Type>>& recvBuffers
) const
{
const auto& AMI = (owner() ? this->AMI() : neighbPatch().AMI());
if (AMI.distributed())
{
const auto& map = (owner() ? AMI.tgtMap() : AMI.srcMap());
// Insert send/receive requests (non-blocking)
map.send(fld, sendRequests, sendBuffers, recvRequests, recvBuffers);
}
}
template<class Type>
void Foam::cyclicAMIPolyPatch::initInterpolate
(
const Field<Type>& fld,
labelRange& sendRequests,
PtrList<List<Type>>& sendBuffers,
labelRange& recvRequests,
PtrList<List<Type>>& recvBuffers
) const
{
const auto& AMI = (owner() ? this->AMI() : neighbPatch().AMI());
if (!AMI.distributed())
{
return;
}
autoPtr<coordSystem::cylindrical> cs;
if (is_vectorspace<Type>::value)
{
cs.reset(cylindricalCS());
}
if (!cs)
{
initInterpolateUntransformed
(
fld,
sendRequests,
sendBuffers,
recvRequests,
recvBuffers
);
}
else
{
const cyclicAMIPolyPatch& nbrPp = this->neighbPatch();
Field<Type> localFld(fld.size());
// Transform to cylindrical coords
{
const tensorField nbrT(cs().R(nbrPp.faceCentres()));
Foam::invTransform(localFld, nbrT, fld);
}
initInterpolateUntransformed
(
localFld,
sendRequests,
sendBuffers,
recvRequests,
recvBuffers
);
}
}
template<class Type>
Foam::tmp<Foam::Field<Type>> Foam::cyclicAMIPolyPatch::interpolate
(
const Field<Type>& localFld,
const labelRange& requests,
const PtrList<List<Type>>& recvBuffers,
const UList<Type>& defaultValues
) const
{
const auto& AMI = (owner() ? this->AMI() : neighbPatch().AMI());
const auto& map = (owner() ? AMI.tgtMap() : AMI.srcMap());
Field<Type> work;
if (AMI.distributed())
{
// Receive (= copy) data from buffers into work. TBD: receive directly
// into slices of work.
map.receive(requests, recvBuffers, work);
}
const Field<Type>& fld = (AMI.distributed() ? work : localFld);
auto tresult = tmp<Field<Type>>::New(this->size(), Zero);
// Note: tresult is optionally in transformed coord system
autoPtr<coordSystem::cylindrical> cs;
if (is_vectorspace<Type>::value)
{
cs.reset(cylindricalCS());
}
if (!cs)
{
AMI.weightedSum
(
owner(),
fld,
tresult.ref(),
defaultValues
);
}
else
{
const tensorField ownT(cs().R(this->faceCentres()));
Field<Type> localDeflt(defaultValues.size());
if (defaultValues.size() == size())
{
// Transform default values into cylindrical coords (using
// *this faceCentres)
// We get in UList (why? Copied from cyclicAMI). Convert to
// Field so we can use transformField routines.
const SubField<Type> defaultSubFld(defaultValues);
const Field<Type>& defaultFld(defaultSubFld);
Foam::invTransform(localDeflt, ownT, defaultFld);
}
AMI.weightedSum
(
owner(),
fld,
tresult.ref(),
localDeflt
);
// Transform back
Foam::transform(tresult.ref(), ownT, tresult());
}
return tresult;
}
template<class Type, class CombineOp>
void Foam::cyclicAMIPolyPatch::interpolate
(
const UList<Type>& fld,
const CombineOp& cop,
List<Type>& result,
const UList<Type>& defaultValues
) const
{
//- Commented out for now since called with non-primitives (e.g. wallPoint
// from FaceCellWave) - missing Foam::transform, Foam::invTransform
/*
autoPtr<coordSystem::cylindrical> cs;
if (is_vectorspace<Type>::value)
{
cs.reset(cylindricalCS());
}
if (cs)
{
const cyclicAMIPolyPatch& nbrPp = this->neighbPatch();
// Transform to cylindrical coords
{
const tensorField nbrT(cs().R(nbrPp.faceCentres()));
Foam::invTransform(result, nbrT, result);
}
const tensorField ownT(cs().R(this->faceCentres()));
Field<Type> localDeflt(defaultValues.size());
if (defaultValues.size() == size())
{
// Transform default values into cylindrical coords (using
// *this faceCentres)
// We get in UList (why? Copied from cyclicAMI). Convert to
// Field so we can use transformField routines.
const SubField<Type> defaultSubFld(defaultValues);
const Field<Type>& defaultFld(defaultSubFld);
Foam::invTransform(localDeflt, ownT, defaultFld);
}
// Do actual AMI interpolation
if (owner())
{
AMI().interpolateToSource
(
fld,
cop,
result,
localDeflt
);
}
else
{
neighbPatch().AMI().interpolateToTarget
(
fld,
cop,
result,
localDeflt
);
}
// Transform back. Result is now at *this
Foam::transform(result, ownT, result);
}
else
*/
{
if (owner())
{
AMI().interpolateToSource
(
fld,
cop,
result,
defaultValues
);
}
else
{
neighbPatch().AMI().interpolateToTarget
(
fld,
cop,
result,
defaultValues
);
}
}
}
// ************************************************************************* //