35 template<
class T,
class CombineOp,
class NegateOp>
47 const label len = map.
size();
51 for (label i = 0; i < len; ++i)
53 const label index = map[i];
57 cop(lhs[index-1], rhs[i]);
61 cop(lhs[-index-1], negOp(rhs[i]));
66 <<
"Illegal flip index '0' at " << i <<
'/' << map.
size()
67 <<
" for list:" << rhs.
size() <<
nl 74 for (label i = 0; i < len; ++i)
76 cop(lhs[map[i]], rhs[i]);
82 template<
class T,
class NegateOp>
92 const label len = map.size();
98 for (label i = 0; i < len; ++i)
100 const label index = map[i];
113 <<
"Illegal flip index '0' at " << i <<
'/' << map.size()
114 <<
" for list:" <<
values.size() <<
nl 122 for (label i = 0; i < len; ++i)
130 template<
class T,
class NegateOp>
136 const NegateOp& negOp
139 List<T>
output(map.size());
145 template<
class T,
class negateOp>
149 const bool subHasFlip,
151 const bool constructHasFlip,
160 const negateOp& negOp,
168 <<
"Only contiguous is currently supported" 178 recvRequests.
size() = 0;
180 recvFields.resize(nProcs);
184 const labelList& map = constructMap[proci];
190 else if (map.empty())
193 (void) recvFields.release(proci);
197 List<T>& subField = recvFields.try_emplace(proci);
204 subField.data_bytes(),
205 subField.size_bytes(),
218 sendRequests.
size() = 0;
220 sendFields.resize(nProcs);
229 (void) sendFields.release(proci);
231 else if (map.empty())
234 (void) sendFields.release(proci);
238 List<T>& subField = sendFields.try_emplace(proci);
241 accessAndFlip(subField,
field, map, subHasFlip, negOp);
247 subField.cdata_bytes(),
248 subField.size_bytes(),
266 (void) recvFields.release(myRank);
270 List<T>& subField = recvFields.try_emplace(myRank);
273 accessAndFlip(subField,
field, map, subHasFlip, negOp);
282 const UList<T>&
field,
283 labelRange& sendRequests,
284 PtrList<List<T>>& sendFields,
285 labelRange& recvRequests,
286 PtrList<List<T>>& recvFields,
297 sendRequests, sendFields,
298 recvRequests, recvFields,
306 template<
class T,
class CombineOp,
class negateOp>
309 const label constructSize,
311 const bool constructHasFlip,
315 const CombineOp& cop,
316 const negateOp& negOp,
324 <<
"Only contiguous is currently supported" 334 DynamicList<int> recvProcs(nProcs);
337 const labelList& map = constructMap[proci];
339 if (proci != myRank && map.size())
343 const auto* subFieldPtr = recvFields.get(proci);
346 checkReceivedSize(proci, map.size(), subFieldPtr->size());
351 <<
"From processor " << proci
352 <<
" : unallocated receive field." 353 <<
" Expected size " << map.size()
354 <<
" on comm " << comm
363 field.resize_nocopy(constructSize);
367 if (recvFields.test(myRank))
369 const labelList& map = constructMap[myRank];
370 const List<T>& subField = recvFields[myRank];
400 for (
const int proci : recvProcs)
402 const labelList& map = constructMap[proci];
403 const List<T>& subField = recvFields[proci];
425 const labelRange& requests,
426 const UPtrList<List<T>>& recvFields,
447 template<
class T,
class CombineOp,
class NegateOp>
452 const label constructSize,
454 const bool subHasFlip,
456 const bool constructHasFlip,
459 const CombineOp& cop,
460 const NegateOp& negOp,
474 accessAndFlip(
field, subMap[myRank], subHasFlip, negOp)
478 const labelList& map = constructMap[myRank];
481 field.resize_nocopy(constructSize);
507 if (proci != myRank && map.size())
511 accessAndFlip(
field, map, subHasFlip, negOp)
515 OPstream
os(commsType, proci, 0, tag, comm);
524 accessAndFlip(
field, subMap[myRank], subHasFlip, negOp)
528 const labelList& map = constructMap[myRank];
531 field.resize_nocopy(constructSize);
548 const labelList& map = constructMap[proci];
550 if (proci != myRank && map.size())
555 checkReceivedSize(proci, map.size(), subField.size());
575 newField.resize_nocopy(constructSize);
576 newField = nullValue;
583 accessAndFlip(
field, subMap[myRank], subHasFlip, negOp)
587 const labelList& map = constructMap[myRank];
602 for (
const labelPair& twoProcs : schedule)
607 if (twoProcs.first() == myRank)
610 const label nbrProc = twoProcs.second();
617 accessAndFlip(
field, map, subHasFlip, negOp)
626 const labelList& map = constructMap[nbrProc];
628 checkReceivedSize(nbrProc, map.size(), subField.size());
644 const label nbrProc = twoProcs.first();
650 const labelList& map = constructMap[nbrProc];
652 checkReceivedSize(nbrProc, map.size(), subField.size());
669 accessAndFlip(
field, map, subHasFlip, negOp)
676 field.transfer(newField);
682 if (!is_contiguous<T>::value)
684 PstreamBuffers pBufs(comm, tag);
691 if (proci != myRank && map.size())
695 accessAndFlip(
field, map, subHasFlip, negOp)
698 UOPstream
os(proci, pBufs);
710 accessAndFlip(
field, subMap[myRank], subHasFlip, negOp)
714 field.resize_nocopy(constructSize);
718 const labelList& map = constructMap[myRank];
737 const labelList& map = constructMap[proci];
739 if (proci != myRank && map.size())
741 UIPstream is(proci, pBufs);
742 List<T> subField(is);
744 checkReceivedSize(proci, map.size(), subField.size());
762 List<List<T>> recvFields(nProcs);
763 DynamicList<int> recvProcs(nProcs);
767 const labelList& map = constructMap[proci];
769 if (proci != myRank && map.size())
772 List<T>& subField = recvFields[proci];
773 subField.resize_nocopy(map.size());
779 subField.data_bytes(),
780 subField.size_bytes(),
790 List<List<T>> sendFields(nProcs);
796 if (proci != myRank && map.size())
798 List<T>& subField = sendFields[proci];
801 accessAndFlip(subField,
field, map, subHasFlip, negOp);
807 subField.cdata_bytes(),
808 subField.size_bytes(),
818 List<T>& subField = recvFields[myRank];
821 accessAndFlip(subField,
field, map, subHasFlip, negOp);
826 field.resize_nocopy(constructSize);
831 const labelList& map = constructMap[myRank];
832 const List<T>& subField = recvFields[myRank];
850 DynamicList<int> indices(recvProcs.size());
861 for (
const int idx : indices)
863 const int proci = recvProcs[idx];
864 const labelList& map = constructMap[proci];
865 const List<T>& subField = recvFields[proci];
889 <<
"Unknown communication schedule " << int(commsType)
895 template<
class T,
class NegateOp>
899 const List<labelPair>& schedule,
900 const label constructSize,
902 const bool subHasFlip,
904 const bool constructHasFlip,
906 const NegateOp& negOp,
920 accessAndFlip(
field, subMap[myRank], subHasFlip, negOp)
924 const labelList& map = constructMap[myRank];
927 field.resize_nocopy(constructSize);
952 if (proci != myRank && map.size())
956 accessAndFlip(
field, map, subHasFlip, negOp)
960 OPstream
os(commsType, proci, 0, tag, comm);
969 accessAndFlip(
field, subMap[myRank], subHasFlip, negOp)
973 const labelList& map = constructMap[myRank];
976 field.resize_nocopy(constructSize);
992 const labelList& map = constructMap[proci];
994 if (proci != myRank && map.size())
999 checkReceivedSize(proci, map.size(), subField.size());
1019 newField.resize_nocopy(constructSize);
1026 accessAndFlip(
field, subMap[myRank], subHasFlip, negOp)
1030 const labelList& map = constructMap[myRank];
1044 for (
const labelPair& twoProcs : schedule)
1049 if (twoProcs.first() == myRank)
1052 const label nbrProc = twoProcs.second();
1058 accessAndFlip(
field, map, subHasFlip, negOp)
1067 const labelList& map = constructMap[nbrProc];
1069 checkReceivedSize(nbrProc, map.size(), subField.size());
1085 const label nbrProc = twoProcs.first();
1091 const labelList& map = constructMap[nbrProc];
1093 checkReceivedSize(nbrProc, map.size(), subField.size());
1109 accessAndFlip(
field, map, subHasFlip, negOp)
1116 field.transfer(newField);
1122 if (!is_contiguous<T>::value)
1124 PstreamBuffers pBufs(comm, tag);
1131 if (proci != myRank && map.size())
1135 accessAndFlip(
field, map, subHasFlip, negOp)
1138 UOPstream
os(proci, pBufs);
1150 accessAndFlip(
field, subMap[myRank], subHasFlip, negOp)
1154 field.resize_nocopy(constructSize);
1157 const labelList& map = constructMap[myRank];
1176 const labelList& map = constructMap[proci];
1178 if (proci != myRank && map.size())
1180 UIPstream is(proci, pBufs);
1181 List<T> subField(is);
1183 checkReceivedSize(proci, map.size(), subField.size());
1201 List<List<T>> recvFields(nProcs);
1202 DynamicList<int> recvProcs(nProcs);
1206 const labelList& map = constructMap[proci];
1208 if (proci != myRank && map.size())
1211 List<T>& subField = recvFields[proci];
1212 subField.resize_nocopy(map.size());
1218 subField.data_bytes(),
1219 subField.size_bytes(),
1229 List<List<T>> sendFields(nProcs);
1235 if (proci != myRank && map.size())
1237 List<T>& subField = sendFields[proci];
1240 accessAndFlip(subField,
field, map, subHasFlip, negOp);
1246 subField.cdata_bytes(),
1247 subField.size_bytes(),
1257 List<T>& subField = recvFields[myRank];
1260 accessAndFlip(subField,
field, map, subHasFlip, negOp);
1265 field.resize_nocopy(constructSize);
1270 const labelList& map = constructMap[myRank];
1271 const List<T>& subField = recvFields[myRank];
1289 DynamicList<int> indices(recvProcs.size());
1300 for (
const int idx : indices)
1302 const int proci = recvProcs[idx];
1303 const labelList& map = constructMap[proci];
1304 const List<T>& subField = recvFields[proci];
1328 <<
"Unknown communication schedule " << int(commsType)
1337 PstreamBuffers& pBufs,
1338 const List<T>&
field 1350 accessAndFlip(
field, map, subHasFlip_, flipOp())
1353 UOPstream
os(proci, pBufs);
1359 pBufs.finishedSends(
false);
1371 field.resize_nocopy(constructSize_);
1375 const labelList& map = constructMap_[proci];
1382 checkReceivedSize(proci, map.
size(), subField.
size());
1398 template<
class T,
class NegateOp>
1403 const NegateOp& negOp,
1410 whichSchedule(commsType),
1424 template<
class T,
class NegateOp>
1430 const NegateOp& negOp,
1437 whichSchedule(commsType),
1453 template<
class T,
class NegateOp>
1457 const NegateOp& negOp,
1492 distribute(commsType, list, tag);
1524 const label constructSize,
1529 reverseDistribute<T, flipOp>
1540 template<
class T,
class NegateOp>
1544 const label constructSize,
1546 const NegateOp& negOp,
1553 whichSchedule(commsType),
1571 const label constructSize,
1580 whichSchedule(commsType),
1601 const label constructSize,
1619 const label constructSize,
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 void accessAndFlip(List< 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.
void send(PstreamBuffers &pBufs, const List< T > &field) const
Do all sends using PstreamBuffers.
static label nRequests() noexcept
Number of outstanding requests (on the internal list of requests)
static rangeType allProcs(const label communicator=worldComm)
Range of process indices for all processes.
A range or interval of labels defined by a start and a size.
constexpr char nl
The newline '\n' character (0x0a)
static bool & parRun() noexcept
Test if this a parallel run.
void resize_nocopy(const label len)
Adjust allocated size of list without necessarily.
static int myProcNo(const label communicator=worldComm)
Rank of this process in the communicator (starting from masterNo()). Can be negative if the process i...
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.
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 label nProcs(const label communicator=worldComm)
Number of ranks in parallel run (for given communicator). It is 1 for serial run. ...
static void recv(Type &value, const int fromProcNo, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm, IOstreamOption::streamFormat fmt=IOstreamOption::BINARY)
Receive and deserialize a value. Uses operator>> for de-serialization.
"scheduled" (MPI standard) : (MPI_Send, MPI_Recv)
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.
IntType start() const noexcept
The (inclusive) lower value of the range.
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.
OBJstream os(runTime.globalPath()/outputName)
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 void flipAndCombine(List< 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...
A list of pointers to objects of type <T>, with allocation/deallocation management of the pointers...
A template class to specify that a data type can be considered as being contiguous in memory...
static bool write(const UPstream::commsTypes commsType, const int toProcNo, const char *buf, const std::streamsize bufSize, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm, UPstream::Request *req=nullptr, const UPstream::sendModes sendMode=UPstream::sendModes::normal)
Write buffer contents to given processor.
"nonBlocking" (immediate) : (MPI_Isend, MPI_Irecv)
static Ostream & output(Ostream &os, const IntRange< T > &range)
List< label > labelList
A List of labels.
IntType size() const noexcept
The size of the range.
"buffered" : (MPI_Bsend, MPI_Recv)
bool send()
Send buffer contents now and not in destructor [advanced usage]. Returns true on success.
Functor to negate primitives. Dummy for most other types.
static void distribute(const UPstream::commsTypes commsType, const List< 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)...
static std::streamsize read(const UPstream::commsTypes commsType, const int fromProcNo, char *buf, const std::streamsize bufSize, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm, UPstream::Request *req=nullptr)
Read buffer contents from given processor.
static bool waitSomeRequests(const label pos, label len=-1, DynamicList< int > *indices=nullptr)
Wait until some requests (from position onwards) have finished. Corresponds to MPI_Waitsome() ...