mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: mapDistribute: add separate input and output
To avoid making initial copy of input to output field.
This commit is contained in:
@ -262,6 +262,7 @@ OptimisationSwitches
|
|||||||
//localAMIComm 0; // old behaviour : all ranks included
|
//localAMIComm 0; // old behaviour : all ranks included
|
||||||
//localAMIComm 1; // (default) only ranks that have patch faces
|
//localAMIComm 1; // (default) only ranks that have patch faces
|
||||||
//localAMIComm 2; // like 1 but always include rank 0 for messages
|
//localAMIComm 2; // like 1 but always include rank 0 for messages
|
||||||
|
localAMIComm 1; // only ranks that have patch faces
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -218,7 +218,7 @@ public:
|
|||||||
void operator()
|
void operator()
|
||||||
(
|
(
|
||||||
const vectorTensorTransform& vt,
|
const vectorTensorTransform& vt,
|
||||||
const bool forward,
|
[[maybe_unused]] const bool forward,
|
||||||
UList<Type>& fld
|
UList<Type>& fld
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
@ -233,7 +233,7 @@ public:
|
|||||||
void operator()
|
void operator()
|
||||||
(
|
(
|
||||||
const vectorTensorTransform& vt,
|
const vectorTensorTransform& vt,
|
||||||
const bool forward,
|
[[maybe_unused]] const bool forward,
|
||||||
List<List<Type>>& flds
|
List<List<Type>>& flds
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2015-2017 OpenFOAM Foundation
|
Copyright (C) 2015-2017 OpenFOAM Foundation
|
||||||
Copyright (C) 2015-2023 OpenCFD Ltd.
|
Copyright (C) 2015-2025 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -909,6 +909,36 @@ public:
|
|||||||
const label comm = UPstream::worldComm
|
const label comm = UPstream::worldComm
|
||||||
);
|
);
|
||||||
|
|
||||||
|
//- Distribute combine data with specified combine operation
|
||||||
|
//- and negate operator (for flips).
|
||||||
|
//
|
||||||
|
// If multiple processors write to same position,
|
||||||
|
// contributions are added using the combine cop.
|
||||||
|
//
|
||||||
|
// \note schedule only used for UPstream::commsTypes::scheduled,
|
||||||
|
// others just use send-to-all, receive-from-all.
|
||||||
|
template<class T, class CombineOp, class NegateOp>
|
||||||
|
static void distribute
|
||||||
|
(
|
||||||
|
const UPstream::commsTypes commsType,
|
||||||
|
const UList<labelPair>& schedule,
|
||||||
|
|
||||||
|
const UList<T>& inField, // input field
|
||||||
|
const labelListList& subMap,
|
||||||
|
const bool subHasFlip,
|
||||||
|
|
||||||
|
List<T>& field, // output field
|
||||||
|
const label constructSize,
|
||||||
|
const labelListList& constructMap,
|
||||||
|
const bool constructHasFlip,
|
||||||
|
const T& nullValue,
|
||||||
|
const CombineOp& cop,
|
||||||
|
const NegateOp& negOp,
|
||||||
|
|
||||||
|
const int tag = UPstream::msgType(),
|
||||||
|
const label comm = UPstream::worldComm
|
||||||
|
);
|
||||||
|
|
||||||
//- Distribute assign data with specified negate operator (for flips).
|
//- Distribute assign data with specified negate operator (for flips).
|
||||||
//- Uses assignment for combine operation.
|
//- Uses assignment for combine operation.
|
||||||
//
|
//
|
||||||
|
|||||||
@ -894,6 +894,275 @@ void Foam::mapDistributeBase::distribute
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class T, class CombineOp, class NegateOp>
|
||||||
|
void Foam::mapDistributeBase::distribute
|
||||||
|
(
|
||||||
|
const UPstream::commsTypes commsType,
|
||||||
|
const UList<labelPair>& schedule,
|
||||||
|
|
||||||
|
const UList<T>& inField, // input field
|
||||||
|
const labelListList& subMap,
|
||||||
|
const bool subHasFlip,
|
||||||
|
|
||||||
|
List<T>& field,
|
||||||
|
const label constructSize,
|
||||||
|
const labelListList& constructMap,
|
||||||
|
const bool constructHasFlip,
|
||||||
|
const T& nullValue,
|
||||||
|
const CombineOp& cop,
|
||||||
|
const NegateOp& negOp,
|
||||||
|
|
||||||
|
const int tag,
|
||||||
|
const label comm
|
||||||
|
)
|
||||||
|
{
|
||||||
|
const auto myRank = UPstream::myProcNo(comm);
|
||||||
|
const auto nProcs = UPstream::nProcs(comm);
|
||||||
|
|
||||||
|
if (!UPstream::parRun())
|
||||||
|
{
|
||||||
|
// Do only me to me.
|
||||||
|
|
||||||
|
List<T> subField
|
||||||
|
(
|
||||||
|
accessAndFlip(inField, subMap[myRank], subHasFlip, negOp)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Receive sub field from myself (subField)
|
||||||
|
const labelList& map = constructMap[myRank];
|
||||||
|
|
||||||
|
// Combining bits - can now reuse field storage
|
||||||
|
field.resize_nocopy(constructSize);
|
||||||
|
field = nullValue;
|
||||||
|
|
||||||
|
flipAndCombine
|
||||||
|
(
|
||||||
|
field,
|
||||||
|
subField,
|
||||||
|
map,
|
||||||
|
constructHasFlip,
|
||||||
|
cop,
|
||||||
|
negOp
|
||||||
|
);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (commsType != UPstream::commsTypes::nonBlocking)
|
||||||
|
{
|
||||||
|
FatalErrorInFunction
|
||||||
|
<< "Unsupport communication type " << int(commsType)
|
||||||
|
<< abort(FatalError);
|
||||||
|
}
|
||||||
|
|
||||||
|
const label startOfRequests = UPstream::nRequests();
|
||||||
|
|
||||||
|
if (!is_contiguous<T>::value)
|
||||||
|
{
|
||||||
|
PstreamBuffers pBufs(comm, tag);
|
||||||
|
|
||||||
|
// Stream data into buffer
|
||||||
|
for (const int proci : UPstream::allProcs(comm))
|
||||||
|
{
|
||||||
|
const labelList& map = subMap[proci];
|
||||||
|
|
||||||
|
if (proci != myRank && map.size())
|
||||||
|
{
|
||||||
|
List<T> subField
|
||||||
|
(
|
||||||
|
accessAndFlip(inField, map, subHasFlip, negOp)
|
||||||
|
);
|
||||||
|
|
||||||
|
UOPstream os(proci, pBufs);
|
||||||
|
os << subField;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initiate receiving - do yet not block
|
||||||
|
pBufs.finishedSends(false);
|
||||||
|
|
||||||
|
{
|
||||||
|
// Set up 'send' to myself
|
||||||
|
List<T> subField
|
||||||
|
(
|
||||||
|
accessAndFlip(inField, subMap[myRank], subHasFlip, negOp)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Combining bits - can now reuse field storage
|
||||||
|
field.resize_nocopy(constructSize);
|
||||||
|
field = nullValue;
|
||||||
|
|
||||||
|
// Receive sub field from myself
|
||||||
|
const labelList& map = constructMap[myRank];
|
||||||
|
|
||||||
|
flipAndCombine
|
||||||
|
(
|
||||||
|
field,
|
||||||
|
subField,
|
||||||
|
map,
|
||||||
|
constructHasFlip,
|
||||||
|
cop,
|
||||||
|
negOp
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for receive requests (and the send requests too)
|
||||||
|
UPstream::waitRequests(startOfRequests);
|
||||||
|
|
||||||
|
// Receive and process neighbour fields
|
||||||
|
for (const int proci : UPstream::allProcs(comm))
|
||||||
|
{
|
||||||
|
const labelList& map = constructMap[proci];
|
||||||
|
|
||||||
|
if (proci != myRank && map.size())
|
||||||
|
{
|
||||||
|
UIPstream is(proci, pBufs);
|
||||||
|
List<T> subField(is);
|
||||||
|
|
||||||
|
checkReceivedSize(proci, map.size(), subField.size());
|
||||||
|
|
||||||
|
flipAndCombine
|
||||||
|
(
|
||||||
|
field,
|
||||||
|
subField,
|
||||||
|
map,
|
||||||
|
constructHasFlip,
|
||||||
|
cop,
|
||||||
|
negOp
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Set up receives from neighbours
|
||||||
|
|
||||||
|
List<List<T>> recvFields(nProcs);
|
||||||
|
DynamicList<int> recvProcs(nProcs);
|
||||||
|
|
||||||
|
for (const int proci : UPstream::allProcs(comm))
|
||||||
|
{
|
||||||
|
const labelList& map = constructMap[proci];
|
||||||
|
|
||||||
|
if (proci != myRank && map.size())
|
||||||
|
{
|
||||||
|
recvProcs.push_back(proci);
|
||||||
|
List<T>& subField = recvFields[proci];
|
||||||
|
subField.resize_nocopy(map.size());
|
||||||
|
|
||||||
|
UIPstream::read
|
||||||
|
(
|
||||||
|
UPstream::commsTypes::nonBlocking,
|
||||||
|
proci,
|
||||||
|
subField.data_bytes(),
|
||||||
|
subField.size_bytes(),
|
||||||
|
tag,
|
||||||
|
comm
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Set up sends to neighbours
|
||||||
|
|
||||||
|
List<List<T>> sendFields(nProcs);
|
||||||
|
|
||||||
|
for (const int proci : UPstream::allProcs(comm))
|
||||||
|
{
|
||||||
|
const labelList& map = subMap[proci];
|
||||||
|
|
||||||
|
if (proci != myRank && map.size())
|
||||||
|
{
|
||||||
|
List<T>& subField = sendFields[proci];
|
||||||
|
subField.resize_nocopy(map.size());
|
||||||
|
|
||||||
|
accessAndFlip(subField, inField, map, subHasFlip, negOp);
|
||||||
|
|
||||||
|
UOPstream::write
|
||||||
|
(
|
||||||
|
UPstream::commsTypes::nonBlocking,
|
||||||
|
proci,
|
||||||
|
subField.cdata_bytes(),
|
||||||
|
subField.size_bytes(),
|
||||||
|
tag,
|
||||||
|
comm
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up 'send' to myself - copy directly into recvFields
|
||||||
|
{
|
||||||
|
const labelList& map = subMap[myRank];
|
||||||
|
List<T>& subField = recvFields[myRank];
|
||||||
|
subField.resize_nocopy(map.size());
|
||||||
|
|
||||||
|
accessAndFlip(subField, inField, map, subHasFlip, negOp);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Combining bits - can now reuse field storage
|
||||||
|
field.resize_nocopy(constructSize);
|
||||||
|
field = nullValue;
|
||||||
|
|
||||||
|
// Receive sub field from myself : recvFields[myRank]
|
||||||
|
{
|
||||||
|
const labelList& map = constructMap[myRank];
|
||||||
|
const List<T>& subField = recvFields[myRank];
|
||||||
|
|
||||||
|
// Probably don't need a size check
|
||||||
|
// checkReceivedSize(myRank, map.size(), subField.size());
|
||||||
|
|
||||||
|
flipAndCombine
|
||||||
|
(
|
||||||
|
field,
|
||||||
|
subField,
|
||||||
|
map,
|
||||||
|
constructHasFlip,
|
||||||
|
cop,
|
||||||
|
negOp
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Poll for completed receive requests and dispatch
|
||||||
|
DynamicList<int> indices(recvProcs.size());
|
||||||
|
while
|
||||||
|
(
|
||||||
|
UPstream::waitSomeRequests
|
||||||
|
(
|
||||||
|
startOfRequests,
|
||||||
|
recvProcs.size(),
|
||||||
|
&indices
|
||||||
|
)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
for (const int idx : indices)
|
||||||
|
{
|
||||||
|
const int proci = recvProcs[idx];
|
||||||
|
const labelList& map = constructMap[proci];
|
||||||
|
const List<T>& subField = recvFields[proci];
|
||||||
|
|
||||||
|
// No size check - was dimensioned above
|
||||||
|
// checkReceivedSize(proci, map.size(), subField.size());
|
||||||
|
|
||||||
|
flipAndCombine
|
||||||
|
(
|
||||||
|
field,
|
||||||
|
subField,
|
||||||
|
map,
|
||||||
|
constructHasFlip,
|
||||||
|
cop,
|
||||||
|
negOp
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for any remaining requests
|
||||||
|
UPstream::waitRequests(startOfRequests);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class T, class NegateOp>
|
template<class T, class NegateOp>
|
||||||
void Foam::mapDistributeBase::distribute
|
void Foam::mapDistributeBase::distribute
|
||||||
(
|
(
|
||||||
|
|||||||
Reference in New Issue
Block a user