35 template<
class T,
class CombineOp,
class NegateOp>
47 const label len = map.
size();
54 for (label i = 0; i < len; ++i)
56 const label index = map[i];
60 cop(lhs[index-1],
rhs[i]);
64 cop(lhs[-index-1], negOp(
rhs[i]));
69 <<
"Illegal flip index '0' at " << i <<
'/' << map.
size()
70 <<
" for list:" <<
rhs.size() <<
nl 77 for (label i = 0; i < len; ++i)
79 cop(lhs[map[i]],
rhs[i]);
85 template<
class T,
class NegateOp>
95 const label len = map.size();
102 for (label i = 0; i < len; ++i)
104 const label index = map[i];
108 output[i] =
values[index-1];
112 output[i] = negOp(
values[-index-1]);
117 <<
"Illegal flip index '0' at " << i <<
'/' << map.size()
118 <<
" for list:" <<
values.size() <<
nl 126 for (label i = 0; i < len; ++i)
128 output[i] =
values[map[i]];
134 template<
class T,
class NegateOp>
140 const NegateOp& negOp
143 List<T> output(map.size());
144 accessAndFlip(output,
values, map, hasFlip, negOp);
149 template<
class T,
class NegateOp>
153 const bool subHasFlip,
155 const bool constructHasFlip,
164 const NegateOp& negOp,
169 if constexpr (!is_contiguous_v<T>)
172 <<
"Only contiguous is currently supported" 182 recvRequests.
size() = 0;
184 recvFields.resize(nProcs);
188 const labelList& map = constructMap[proci];
194 else if (map.empty())
197 (void) recvFields.release(proci);
201 List<T>& subField = recvFields.try_emplace(proci);
221 sendRequests.
size() = 0;
223 sendFields.resize(nProcs);
232 (void) sendFields.release(proci);
234 else if (map.empty())
237 (void) sendFields.release(proci);
241 List<T>& subField = sendFields.try_emplace(proci);
244 accessAndFlip(subField,
field, map, subHasFlip, negOp);
268 (void) recvFields.release(myRank);
272 List<T>& subField = recvFields.try_emplace(myRank);
275 accessAndFlip(subField,
field, map, subHasFlip, negOp);
284 const UList<T>&
field,
285 labelRange& sendRequests,
286 PtrList<List<T>>& sendFields,
287 labelRange& recvRequests,
288 PtrList<List<T>>& recvFields,
299 sendRequests, sendFields,
300 recvRequests, recvFields,
308 template<
class T,
class CombineOp,
class NegateOp>
311 const label constructSize,
313 const bool constructHasFlip,
317 const CombineOp& cop,
318 const NegateOp& negOp,
323 if constexpr (!is_contiguous_v<T>)
326 <<
"Only contiguous is currently supported" 337 DynamicList<int> recvProcs(nProcs);
340 const labelList& map = constructMap[proci];
342 if (proci != myRank && map.size())
346 const auto* subFieldPtr = recvFields.get(proci);
349 checkReceivedSize(proci, map.size(), subFieldPtr->size());
354 <<
"From processor " << proci
355 <<
" : unallocated receive field." 356 <<
" Expected size " << map.size()
357 <<
" on comm " << comm
366 field.resize_nocopy(constructSize);
370 if (recvFields.test(myRank))
372 const labelList& map = constructMap[myRank];
373 const List<T>& subField = recvFields[myRank];
403 for (
const int proci : recvProcs)
405 const labelList& map = constructMap[proci];
406 const List<T>& subField = recvFields[proci];
428 const labelRange& requests,
429 const UPtrList<List<T>>& recvFields,
450 template<
class T,
class CombineOp,
class NegateOp>
455 const label constructSize,
457 const bool subHasFlip,
459 const bool constructHasFlip,
462 const CombineOp& cop,
463 const NegateOp& negOp,
478 accessAndFlip(
field, subMap[myRank], subHasFlip, negOp)
482 const labelList& map = constructMap[myRank];
485 field.resize_nocopy(constructSize);
511 if (proci != myRank && map.size())
515 accessAndFlip(
field, map, subHasFlip, negOp)
519 OPstream os(commsType, proci, 0, tag, comm);
528 accessAndFlip(
field, subMap[myRank], subHasFlip, negOp)
532 const labelList& map = constructMap[myRank];
535 field.resize_nocopy(constructSize);
552 const labelList& map = constructMap[proci];
554 if (proci != myRank && map.size())
559 checkReceivedSize(proci, map.size(), subField.size());
579 newField.resize_nocopy(constructSize);
580 newField = nullValue;
587 accessAndFlip(
field, subMap[myRank], subHasFlip, negOp)
591 const labelList& map = constructMap[myRank];
606 for (
const labelPair& twoProcs : schedule)
611 if (twoProcs.first() == myRank)
614 const label nbrProc = twoProcs.second();
621 accessAndFlip(
field, map, subHasFlip, negOp)
630 const labelList& map = constructMap[nbrProc];
632 checkReceivedSize(nbrProc, map.size(), subField.size());
648 const label nbrProc = twoProcs.first();
654 const labelList& map = constructMap[nbrProc];
656 checkReceivedSize(nbrProc, map.size(), subField.size());
673 accessAndFlip(
field, map, subHasFlip, negOp)
680 field.transfer(newField);
686 if constexpr (!is_contiguous_v<T>)
688 PstreamBuffers pBufs(comm, tag);
695 if (proci != myRank && map.size())
699 accessAndFlip(
field, map, subHasFlip, negOp)
702 UOPstream os(proci, pBufs);
714 accessAndFlip(
field, subMap[myRank], subHasFlip, negOp)
718 field.resize_nocopy(constructSize);
722 const labelList& map = constructMap[myRank];
741 const labelList& map = constructMap[proci];
743 if (proci != myRank && map.size())
745 UIPstream is(proci, pBufs);
746 List<T> subField(is);
748 checkReceivedSize(proci, map.size(), subField.size());
766 List<List<T>> recvFields(nProcs);
767 DynamicList<int> recvProcs(nProcs);
771 const labelList& map = constructMap[proci];
773 if (proci != myRank && map.size())
776 List<T>& subField = recvFields[proci];
777 subField.resize_nocopy(map.size());
793 List<List<T>> sendFields(nProcs);
799 if (proci != myRank && map.size())
801 List<T>& subField = sendFields[proci];
804 accessAndFlip(subField,
field, map, subHasFlip, negOp);
820 List<T>& subField = recvFields[myRank];
823 accessAndFlip(subField,
field, map, subHasFlip, negOp);
828 field.resize_nocopy(constructSize);
833 const labelList& map = constructMap[myRank];
834 const List<T>& subField = recvFields[myRank];
852 DynamicList<int> indices(recvProcs.size());
863 for (
const int idx : indices)
865 const int proci = recvProcs[idx];
866 const labelList& map = constructMap[proci];
867 const List<T>& subField = recvFields[proci];
891 <<
"Unknown communication schedule " << int(commsType)
897 template<
class T,
class CombineOp,
class NegateOp>
901 const UList<labelPair>& schedule,
903 const UList<T>& inField,
905 const bool subHasFlip,
908 const label constructSize,
910 const bool constructHasFlip,
912 const CombineOp& cop,
913 const NegateOp& negOp,
928 accessAndFlip(inField, subMap[myRank], subHasFlip, negOp)
932 const labelList& map = constructMap[myRank];
935 field.resize_nocopy(constructSize);
954 <<
"Unsupport communication type " << int(commsType)
960 if constexpr (!is_contiguous_v<T>)
962 PstreamBuffers pBufs(comm, tag);
969 if (proci != myRank && map.size())
973 accessAndFlip(inField, map, subHasFlip, negOp)
976 UOPstream os(proci, pBufs);
988 accessAndFlip(inField, subMap[myRank], subHasFlip, negOp)
992 field.resize_nocopy(constructSize);
996 const labelList& map = constructMap[myRank];
1015 const labelList& map = constructMap[proci];
1017 if (proci != myRank && map.size())
1019 UIPstream is(proci, pBufs);
1020 List<T> subField(is);
1022 checkReceivedSize(proci, map.size(), subField.size());
1040 List<List<T>> recvFields(nProcs);
1041 DynamicList<int> recvProcs(nProcs);
1045 const labelList& map = constructMap[proci];
1047 if (proci != myRank && map.size())
1050 List<T>& subField = recvFields[proci];
1051 subField.resize_nocopy(map.size());
1057 subField.data_bytes(),
1058 subField.size_bytes(),
1068 List<List<T>> sendFields(nProcs);
1074 if (proci != myRank && map.size())
1076 List<T>& subField = sendFields[proci];
1079 accessAndFlip(subField, inField, map, subHasFlip, negOp);
1085 subField.cdata_bytes(),
1086 subField.size_bytes(),
1096 List<T>& subField = recvFields[myRank];
1099 accessAndFlip(subField, inField, map, subHasFlip, negOp);
1104 field.resize_nocopy(constructSize);
1109 const labelList& map = constructMap[myRank];
1110 const List<T>& subField = recvFields[myRank];
1128 DynamicList<int> indices(recvProcs.size());
1139 for (
const int idx : indices)
1141 const int proci = recvProcs[idx];
1142 const labelList& map = constructMap[proci];
1143 const List<T>& subField = recvFields[proci];
1166 template<
class T,
class NegateOp>
1170 const UList<labelPair>& schedule,
1171 const label constructSize,
1173 const bool subHasFlip,
1175 const bool constructHasFlip,
1177 const NegateOp& negOp,
1192 accessAndFlip(
field, subMap[myRank], subHasFlip, negOp)
1196 const labelList& map = constructMap[myRank];
1199 field.resize_nocopy(constructSize);
1224 if (proci != myRank && map.size())
1228 accessAndFlip(
field, map, subHasFlip, negOp)
1232 OPstream os(commsType, proci, 0, tag, comm);
1241 accessAndFlip(
field, subMap[myRank], subHasFlip, negOp)
1245 const labelList& map = constructMap[myRank];
1248 field.resize_nocopy(constructSize);
1264 const labelList& map = constructMap[proci];
1266 if (proci != myRank && map.size())
1271 checkReceivedSize(proci, map.size(), subField.size());
1291 newField.resize_nocopy(constructSize);
1298 accessAndFlip(
field, subMap[myRank], subHasFlip, negOp)
1302 const labelList& map = constructMap[myRank];
1316 for (
const labelPair& twoProcs : schedule)
1321 if (twoProcs.first() == myRank)
1324 const label nbrProc = twoProcs.second();
1330 accessAndFlip(
field, map, subHasFlip, negOp)
1339 const labelList& map = constructMap[nbrProc];
1341 checkReceivedSize(nbrProc, map.size(), subField.size());
1357 const label nbrProc = twoProcs.first();
1363 const labelList& map = constructMap[nbrProc];
1365 checkReceivedSize(nbrProc, map.size(), subField.size());
1381 accessAndFlip(
field, map, subHasFlip, negOp)
1388 field.transfer(newField);
1394 if constexpr (!is_contiguous_v<T>)
1396 PstreamBuffers pBufs(comm, tag);
1403 if (proci != myRank && map.size())
1407 accessAndFlip(
field, map, subHasFlip, negOp)
1410 UOPstream os(proci, pBufs);
1422 accessAndFlip(
field, subMap[myRank], subHasFlip, negOp)
1426 field.resize_nocopy(constructSize);
1429 const labelList& map = constructMap[myRank];
1448 const labelList& map = constructMap[proci];
1450 if (proci != myRank && map.size())
1452 UIPstream is(proci, pBufs);
1453 List<T> subField(is);
1455 checkReceivedSize(proci, map.size(), subField.size());
1473 List<List<T>> recvFields(nProcs);
1474 DynamicList<int> recvProcs(nProcs);
1478 const labelList& map = constructMap[proci];
1480 if (proci != myRank && map.size())
1483 List<T>& subField = recvFields[proci];
1484 subField.resize_nocopy(map.size());
1500 List<List<T>> sendFields(nProcs);
1506 if (proci != myRank && map.size())
1508 List<T>& subField = sendFields[proci];
1511 accessAndFlip(subField,
field, map, subHasFlip, negOp);
1527 List<T>& subField = recvFields[myRank];
1530 accessAndFlip(subField,
field, map, subHasFlip, negOp);
1535 field.resize_nocopy(constructSize);
1540 const labelList& map = constructMap[myRank];
1541 const List<T>& subField = recvFields[myRank];
1559 DynamicList<int> indices(recvProcs.size());
1570 for (
const int idx : indices)
1572 const int proci = recvProcs[idx];
1573 const labelList& map = constructMap[proci];
1574 const List<T>& subField = recvFields[proci];
1598 <<
"Unknown communication schedule " << int(commsType)
1607 PstreamBuffers& pBufs,
1608 const UList<T>&
field 1620 accessAndFlip(
field, map, subHasFlip_, flipOp())
1623 UOPstream os(proci, pBufs);
1629 pBufs.finishedSends(
false);
1641 field.resize_nocopy(constructSize_);
1645 const labelList& map = constructMap_[proci];
1652 checkReceivedSize(proci, map.
size(), subField.
size());
1668 template<
class T,
class NegateOp>
1673 const NegateOp& negOp,
1680 whichSchedule(commsType),
1694 template<
class T,
class NegateOp>
1700 const NegateOp& negOp,
1707 whichSchedule(commsType),
1723 template<
class T,
class NegateOp>
1727 const NegateOp& negOp,
1760 distribute(commsType, work, tag);
1762 values = std::move(work);
1792 const label constructSize,
1797 reverseDistribute<T, flipOp>
1808 template<
class T,
class NegateOp>
1812 const label constructSize,
1814 const NegateOp& negOp,
1821 whichSchedule(commsType),
1839 const label constructSize,
1848 whichSchedule(commsType),
1869 const label constructSize,
1887 const label constructSize,
void send(PstreamBuffers &pBufs, const UList< T > &field) const
Do all sends using PstreamBuffers.
void size(const label n)
Older name for setAddressableSize.
errorManipArg< error, int > exit(error &err, const int errNo=1)
commsTypes
Communications types.
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
static label nRequests() noexcept
Number of outstanding requests (on the internal list of requests)
A range or interval of labels defined by a start and a size.
constexpr char nl
The newline '\n' character (0x0a)
static bool waitSomeRequests(label pos, label len=-1, DynamicList< int > *indices=nullptr)
Wait until some requests (from position onwards) have finished. Corresponds to MPI_Waitsome() ...
static bool & parRun() noexcept
Test if this a parallel run.
static int myProcNo(label communicator=worldComm)
Rank of this process in the communicator (starting from masterNo()). Negative if the process is not a...
void resize_nocopy(const label len)
Adjust allocated size of list without necessarily.
static std::streamsize read(const UPstream::commsTypes commsType, const int fromProcNo, Type *buffer, std::streamsize count, const int tag=UPstream::msgType(), const int communicator=UPstream::worldComm, UPstream::Request *req=nullptr)
Receive buffer contents (contiguous types) from given processor.
void push_back(const T &val)
Append an element at the end of the list.
List< labelList > labelListList
List of labelList.
static void waitRequests()
Wait for all requests to finish.
UList< label > labelUList
A UList of labels.
static rangeType allProcs(label communicator=worldComm)
Range of process indices for all processes.
void rhs(fvMatrix< typename Expr::value_type > &m, const Expr &expression)
List< T > values(const HashTable< T, Key, Hash > &tbl, const bool doSort=false)
List of values from HashTable, optionally sorted.
Input inter-processor communications stream using MPI send/recv etc. - operating on external buffer...
static void accessAndFlip(UList< T > &output, const UList< T > &values, const labelUList &map, const bool hasFlip, const NegateOp &negOp)
Lookup field values at specified map indices and save after any flip negation operations.
"scheduled" (MPI standard) : (MPI_Send, MPI_Recv)
static void recv(Type &value, const int fromProcNo, const int tag=UPstream::msgType(), const int communicator=UPstream::worldComm, IOstreamOption::streamFormat fmt=IOstreamOption::BINARY)
Receive and deserialize a value. Uses operator>> for de-serialization.
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects...
void finishedSends(const bool wait=true)
Mark the send phase as being finished.
void reverseDistribute(const label constructSize, List< T > &values, const int tag=UPstream::msgType()) const
Reverse distribute data using default commsType and the default flip/negate operator.
static void flipAndCombine(UList< T > &lhs, const UList< T > &rhs, const labelUList &map, const bool hasFlip, const CombineOp &cop, const NegateOp &negOp)
Combine field values (after any flip negation operation) into the specified mapped target locations...
static bool write(const UPstream::commsTypes commsType, const int toProcNo, const Type *buffer, std::streamsize count, const int tag=UPstream::msgType(), const int communicator=UPstream::worldComm, UPstream::Request *req=nullptr, const UPstream::sendModes sendMode=UPstream::sendModes::normal)
Write buffer contents (contiguous types only) to given processor.
A list of pointers to objects of type <T>, without allocation/deallocation management of the pointers...
errorManip< error > abort(error &err)
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Pair< label > labelPair
A pair of labels.
Buffers for inter-processor communications streams (UOPstream, UIPstream).
void T(FieldField< Field, Type > &f1, const FieldField< Field, Type > &f2)
void receive(PstreamBuffers &pBufs, List< T > &field) const
Do all receives using PstreamBuffers.
static commsTypes defaultCommsType
Default commsType.
static label nProcs(label communicator=worldComm)
Number of ranks in parallel run (for given communicator). It is 1 for serial run. ...
A list of pointers to objects of type <T>, with allocation/deallocation management of the pointers...
constexpr IntType size() const noexcept
The size of the range.
constexpr IntType start() const noexcept
The (inclusive) lower value of the range.
"nonBlocking" (immediate) : (MPI_Isend, MPI_Irecv)
List< label > labelList
A List of labels.
"buffered" : (MPI_Bsend, MPI_Recv)
bool send()
Send buffer contents now and not in destructor [advanced usage]. Returns true on success.
Negation for scalar/vectorspace/etc, otherwise pass through.
static void distribute(const UPstream::commsTypes commsType, const UList< labelPair > &schedule, const label constructSize, const labelListList &subMap, const bool subHasFlip, const labelListList &constructMap, const bool constructHasFlip, List< T > &field, const T &nullValue, const CombineOp &cop, const NegateOp &negOp, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
Distribute combine data with specified combine operation and negate operator (for flips)...