1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM is free software: you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by
13 the Free Software Foundation, either version 3 of the License, or
14 (at your option) any later version.
16 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
24 \*---------------------------------------------------------------------------*/
26 #include "mapDistribute.H"
27 #include "commSchedule.H"
29 #include "globalIndex.H"
30 #include "globalIndexAndTransform.H"
31 #include "transformField.H"
34 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
36 defineTypeNameAndDebug(Foam::mapDistribute, 0);
38 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
41 void Foam::mapDistribute::transform::operator()
43 const vectorTensorTransform&,
49 void Foam::mapDistribute::transform::operator()
51 const coupledPolyPatch&,
56 void Foam::mapDistribute::transform::operator()
58 const coupledPolyPatch&,
63 void Foam::mapDistribute::transform::operator()
65 const coupledPolyPatch&,
72 void Foam::mapDistribute::transform::operator()
74 const vectorTensorTransform&,
80 void Foam::mapDistribute::transform::operator()
82 const coupledPolyPatch&,
87 void Foam::mapDistribute::transform::operator()
89 const coupledPolyPatch&,
94 void Foam::mapDistribute::transform::operator()
96 const coupledPolyPatch&,
103 void Foam::mapDistribute::transform::operator()
105 const vectorTensorTransform&,
111 void Foam::mapDistribute::transform::operator()
113 const coupledPolyPatch&,
118 void Foam::mapDistribute::transform::operator()
120 const coupledPolyPatch&,
125 void Foam::mapDistribute::transform::operator()
127 const coupledPolyPatch&,
133 Foam::List<Foam::labelPair> Foam::mapDistribute::schedule
135 const labelListList& subMap,
136 const labelListList& constructMap
139 // Communications: send and receive processor
140 List<labelPair> allComms;
143 HashSet<labelPair, labelPair::Hash<> > commsSet(Pstream::nProcs());
145 // Find what communication is required
146 forAll(subMap, procI)
148 if (procI != Pstream::myProcNo())
150 if (subMap[procI].size())
152 // I need to send to procI
153 commsSet.insert(labelPair(Pstream::myProcNo(), procI));
155 if (constructMap[procI].size())
157 // I need to receive from procI
158 commsSet.insert(labelPair(procI, Pstream::myProcNo()));
162 allComms = commsSet.toc();
167 if (Pstream::master())
172 int slave=Pstream::firstSlave();
173 slave<=Pstream::lastSlave();
177 IPstream fromSlave(Pstream::scheduled, slave);
178 List<labelPair> nbrData(fromSlave);
182 if (findIndex(allComms, nbrData[i]) == -1)
184 label sz = allComms.size();
185 allComms.setSize(sz+1);
186 allComms[sz] = nbrData[i];
193 int slave=Pstream::firstSlave();
194 slave<=Pstream::lastSlave();
198 OPstream toSlave(Pstream::scheduled, slave);
205 OPstream toMaster(Pstream::scheduled, Pstream::masterNo());
206 toMaster << allComms;
209 IPstream fromMaster(Pstream::scheduled, Pstream::masterNo());
210 fromMaster >> allComms;
215 // Determine my schedule.
222 ).procSchedule()[Pstream::myProcNo()]
225 // Processors involved in my schedule
226 return List<labelPair>(UIndirectList<labelPair>(allComms, mySchedule));
231 // Pout<< "I need to:" << endl;
232 // const List<labelPair>& comms = schedule();
235 // const labelPair& twoProcs = comms[i];
236 // label sendProc = twoProcs[0];
237 // label recvProc = twoProcs[1];
239 // if (recvProc == Pstream::myProcNo())
241 // Pout<< " receive from " << sendProc << endl;
245 // Pout<< " send to " << recvProc << endl;
252 const Foam::List<Foam::labelPair>& Foam::mapDistribute::schedule() const
254 if (schedulePtr_.empty())
260 schedule(subMap_, constructMap_)
264 return schedulePtr_();
268 void Foam::mapDistribute::checkReceivedSize
271 const label expectedSize,
272 const label receivedSize
275 if (receivedSize != expectedSize)
279 "template<class T>\n"
280 "void mapDistribute::distribute\n"
282 " const Pstream::commsTypes commsType,\n"
283 " const List<labelPair>& schedule,\n"
284 " const label constructSize,\n"
285 " const labelListList& subMap,\n"
286 " const labelListList& constructMap,\n"
289 ) << "Expected from processor " << procI
290 << " " << expectedSize << " but received "
291 << receivedSize << " elements."
292 << abort(FatalError);
297 void Foam::mapDistribute::printLayout(Ostream& os) const
299 // Determine offsets of remote data.
300 labelList minIndex(Pstream::nProcs(), labelMax);
301 labelList maxIndex(Pstream::nProcs(), labelMin);
302 forAll(constructMap_, procI)
304 const labelList& construct = constructMap_[procI];
305 minIndex[procI] = min(minIndex[procI], min(construct));
306 maxIndex[procI] = max(maxIndex[procI], max(construct));
310 if (maxIndex[Pstream::myProcNo()] == labelMin)
316 localSize = maxIndex[Pstream::myProcNo()]+1;
319 os << "Layout: (constructSize:" << constructSize_ << ")" << endl
320 << "local (processor " << Pstream::myProcNo() << "):" << endl
321 << " start : 0" << endl
322 << " size : " << localSize << endl;
324 label offset = localSize;
325 forAll(minIndex, procI)
327 if (procI != Pstream::myProcNo())
329 if (constructMap_[procI].size() > 0)
331 if (minIndex[procI] != offset)
333 FatalErrorIn("mapDistribute::printLayout(..)")
334 << "offset:" << offset
335 << " procI:" << procI
336 << " minIndex:" << minIndex[procI]
337 << abort(FatalError);
340 label size = maxIndex[procI]-minIndex[procI]+1;
341 os << "processor " << procI << ':' << endl
342 << " start : " << offset << endl
343 << " size : " << size << endl;
349 forAll(transformElements_, trafoI)
351 if (transformElements_[trafoI].size() > 0)
353 os << "transform " << trafoI << ':' << endl
354 << " start : " << transformStart_[trafoI] << endl
355 << " size : " << transformElements_[trafoI].size() << endl;
361 // Construct per processor compact addressing of the global elements
362 // needed. The ones from the local processor are not included since
363 // these are always all needed.
364 void Foam::mapDistribute::calcCompactAddressing
366 const globalIndex& globalNumbering,
367 const labelList& elements,
368 List<Map<label> >& compactMap
371 compactMap.setSize(Pstream::nProcs());
373 // Count all (non-local) elements needed. Just for presizing map.
374 labelList nNonLocal(Pstream::nProcs(), 0);
378 label globalIndex = elements[i];
380 if (globalIndex != -1 && !globalNumbering.isLocal(globalIndex))
382 label procI = globalNumbering.whichProcID(globalIndex);
387 forAll(compactMap, procI)
389 compactMap[procI].clear();
390 if (procI != Pstream::myProcNo())
392 compactMap[procI].resize(2*nNonLocal[procI]);
397 // Collect all (non-local) elements needed.
400 label globalIndex = elements[i];
402 if (globalIndex != -1 && !globalNumbering.isLocal(globalIndex))
404 label procI = globalNumbering.whichProcID(globalIndex);
405 label index = globalNumbering.toLocal(procI, globalIndex);
406 label nCompact = compactMap[procI].size();
407 compactMap[procI].insert(index, nCompact);
413 void Foam::mapDistribute::calcCompactAddressing
415 const globalIndex& globalNumbering,
416 const labelListList& cellCells,
417 List<Map<label> >& compactMap
420 compactMap.setSize(Pstream::nProcs());
422 // Count all (non-local) elements needed. Just for presizing map.
423 labelList nNonLocal(Pstream::nProcs(), 0);
425 forAll(cellCells, cellI)
427 const labelList& cCells = cellCells[cellI];
431 label globalIndex = cCells[i];
433 if (globalIndex != -1 && !globalNumbering.isLocal(globalIndex))
435 label procI = globalNumbering.whichProcID(globalIndex);
441 forAll(compactMap, procI)
443 compactMap[procI].clear();
444 if (procI != Pstream::myProcNo())
446 compactMap[procI].resize(2*nNonLocal[procI]);
451 // Collect all (non-local) elements needed.
452 forAll(cellCells, cellI)
454 const labelList& cCells = cellCells[cellI];
458 label globalIndex = cCells[i];
460 if (globalIndex != -1 && !globalNumbering.isLocal(globalIndex))
462 label procI = globalNumbering.whichProcID(globalIndex);
463 label index = globalNumbering.toLocal(procI, globalIndex);
464 label nCompact = compactMap[procI].size();
465 compactMap[procI].insert(index, nCompact);
472 void Foam::mapDistribute::exchangeAddressing
474 const globalIndex& globalNumbering,
476 List<Map<label> >& compactMap,
477 labelList& compactStart
480 // The overall compact addressing is
481 // - myProcNo data first (uncompacted)
482 // - all other processors consecutively
484 compactStart.setSize(Pstream::nProcs());
485 compactStart[Pstream::myProcNo()] = 0;
486 constructSize_ = globalNumbering.localSize();
487 forAll(compactStart, procI)
489 if (procI != Pstream::myProcNo())
491 compactStart[procI] = constructSize_;
492 constructSize_ += compactMap[procI].size();
498 // Find out what to receive/send in compact addressing.
500 // What I want to receive is what others have to send
501 labelListList wantedRemoteElements(Pstream::nProcs());
502 // Compact addressing for received data
503 constructMap_.setSize(Pstream::nProcs());
504 forAll(compactMap, procI)
506 if (procI == Pstream::myProcNo())
508 // All my own elements are used
509 label nLocal = globalNumbering.localSize();
510 wantedRemoteElements[procI] = identity(nLocal);
511 constructMap_[procI] = identity(nLocal);
515 // Remote elements wanted from processor procI
516 labelList& remoteElem = wantedRemoteElements[procI];
517 labelList& localElem = constructMap_[procI];
518 remoteElem.setSize(compactMap[procI].size());
519 localElem.setSize(compactMap[procI].size());
521 forAllIter(Map<label>, compactMap[procI], iter)
523 const label compactI = compactStart[procI] + iter();
524 remoteElem[i] = iter.key();
525 localElem[i] = compactI;
532 subMap_.setSize(Pstream::nProcs());
533 labelListList sendSizes;
534 Pstream::exchange<labelList, label>
536 wantedRemoteElements,
544 elements[i] = renumber(globalNumbering, compactMap, elements[i]);
549 void Foam::mapDistribute::exchangeAddressing
551 const globalIndex& globalNumbering,
552 labelListList& cellCells,
553 List<Map<label> >& compactMap,
554 labelList& compactStart
557 // The overall compact addressing is
558 // - myProcNo data first (uncompacted)
559 // - all other processors consecutively
561 compactStart.setSize(Pstream::nProcs());
562 compactStart[Pstream::myProcNo()] = 0;
563 constructSize_ = globalNumbering.localSize();
564 forAll(compactStart, procI)
566 if (procI != Pstream::myProcNo())
568 compactStart[procI] = constructSize_;
569 constructSize_ += compactMap[procI].size();
575 // Find out what to receive/send in compact addressing.
577 // What I want to receive is what others have to send
578 labelListList wantedRemoteElements(Pstream::nProcs());
579 // Compact addressing for received data
580 constructMap_.setSize(Pstream::nProcs());
581 forAll(compactMap, procI)
583 if (procI == Pstream::myProcNo())
585 // All my own elements are used
586 label nLocal = globalNumbering.localSize();
587 wantedRemoteElements[procI] = identity(nLocal);
588 constructMap_[procI] = identity(nLocal);
592 // Remote elements wanted from processor procI
593 labelList& remoteElem = wantedRemoteElements[procI];
594 labelList& localElem = constructMap_[procI];
595 remoteElem.setSize(compactMap[procI].size());
596 localElem.setSize(compactMap[procI].size());
598 forAllIter(Map<label>, compactMap[procI], iter)
600 const label compactI = compactStart[procI] + iter();
601 remoteElem[i] = iter.key();
602 localElem[i] = compactI;
609 subMap_.setSize(Pstream::nProcs());
610 labelListList sendSizes;
611 Pstream::exchange<labelList, label>
613 wantedRemoteElements,
619 forAll(cellCells, cellI)
621 labelList& cCells = cellCells[cellI];
625 cCells[i] = renumber(globalNumbering, compactMap, cCells[i]);
631 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
634 Foam::mapDistribute::mapDistribute()
641 //- Construct from components
642 Foam::mapDistribute::mapDistribute
644 const label constructSize,
645 const Xfer<labelListList>& subMap,
646 const Xfer<labelListList>& constructMap
649 constructSize_(constructSize),
651 constructMap_(constructMap),
656 //- Construct from components
657 Foam::mapDistribute::mapDistribute
659 const label constructSize,
660 const Xfer<labelListList>& subMap,
661 const Xfer<labelListList>& constructMap,
662 const Xfer<labelListList>& transformElements,
663 const Xfer<labelList>& transformStart
666 constructSize_(constructSize),
668 constructMap_(constructMap),
669 transformElements_(transformElements),
670 transformStart_(transformStart),
675 Foam::mapDistribute::mapDistribute
677 const labelList& sendProcs,
678 const labelList& recvProcs
684 if (sendProcs.size() != recvProcs.size())
688 "mapDistribute::mapDistribute(const labelList&, const labelList&)"
689 ) << "The send and receive data is not the same length. sendProcs:"
690 << sendProcs.size() << " recvProcs:" << recvProcs.size()
691 << abort(FatalError);
694 // Per processor the number of samples we have to send/receive.
695 labelList nSend(Pstream::nProcs(), 0);
696 labelList nRecv(Pstream::nProcs(), 0);
698 forAll(sendProcs, sampleI)
700 label sendProc = sendProcs[sampleI];
701 label recvProc = recvProcs[sampleI];
703 // Note that also need to include local communication (both
704 // RecvProc and sendProc on local processor)
706 if (Pstream::myProcNo() == sendProc)
708 // I am the sender. Count destination processor.
711 if (Pstream::myProcNo() == recvProc)
713 // I am the receiver.
718 subMap_.setSize(Pstream::nProcs());
719 constructMap_.setSize(Pstream::nProcs());
722 subMap_[procI].setSize(nSend[procI]);
723 constructMap_[procI].setSize(nRecv[procI]);
728 forAll(sendProcs, sampleI)
730 label sendProc = sendProcs[sampleI];
731 label recvProc = recvProcs[sampleI];
733 if (Pstream::myProcNo() == sendProc)
735 // I am the sender. Store index I need to send.
736 subMap_[recvProc][nSend[recvProc]++] = sampleI;
738 if (Pstream::myProcNo() == recvProc)
740 // I am the receiver.
741 constructMap_[sendProc][nRecv[sendProc]++] = sampleI;
742 // Largest entry inside constructMap
743 constructSize_ = sampleI+1;
749 Foam::mapDistribute::mapDistribute
751 const globalIndex& globalNumbering,
753 List<Map<label> >& compactMap
759 // Construct per processor compact addressing of the global elements
760 // needed. The ones from the local processor are not included since
761 // these are always all needed.
762 calcCompactAddressing
769 //// Sort remote elements needed (not really necessary)
770 //forAll(compactMap, procI)
772 // if (procI != Pstream::myProcNo())
774 // Map<label>& globalMap = compactMap[procI];
776 // SortableList<label> sorted(globalMap.toc().xfer());
780 // Map<label>::iterator iter = globalMap.find(sorted[i]);
787 // Exchange what I need with processor that supplies it. Renumber elements
788 // into compact numbering
789 labelList compactStart;
805 Foam::mapDistribute::mapDistribute
807 const globalIndex& globalNumbering,
808 labelListList& cellCells,
809 List<Map<label> >& compactMap
815 // Construct per processor compact addressing of the global elements
816 // needed. The ones from the local processor are not included since
817 // these are always all needed.
818 calcCompactAddressing
825 //// Sort remote elements needed (not really necessary)
826 //forAll(compactMap, procI)
828 // if (procI != Pstream::myProcNo())
830 // Map<label>& globalMap = compactMap[procI];
832 // SortableList<label> sorted(globalMap.toc().xfer());
836 // Map<label>::iterator iter = globalMap.find(sorted[i]);
843 // Exchange what I need with processor that supplies it. Renumber elements
844 // into compact numbering
845 labelList compactStart;
861 Foam::mapDistribute::mapDistribute
863 const globalIndex& globalNumbering,
865 const globalIndexAndTransform& globalTransforms,
866 const labelPairList& transformedElements,
867 labelList& transformedIndices,
868 List<Map<label> >& compactMap
874 // Construct per processor compact addressing of the global elements
875 // needed. The ones from the local processor are not included since
876 // these are always all needed.
877 calcCompactAddressing
884 // Add all (non-local) transformed elements needed.
885 forAll(transformedElements, i)
887 labelPair elem = transformedElements[i];
888 label procI = globalIndexAndTransform::processor(elem);
889 if (procI != Pstream::myProcNo())
891 label index = globalIndexAndTransform::index(elem);
892 label nCompact = compactMap[procI].size();
893 compactMap[procI].insert(index, nCompact);
898 // Exchange what I need with processor that supplies it. Renumber elements
899 // into compact numbering
900 labelList compactStart;
910 // Renumber the transformed elements
911 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
912 // Count per transformIndex
913 label nTrafo = globalTransforms.transformPermutations().size();
914 labelList nPerTransform(nTrafo, 0);
915 forAll(transformedElements, i)
917 labelPair elem = transformedElements[i];
918 label trafoI = globalIndexAndTransform::transformIndex(elem);
919 nPerTransform[trafoI]++;
921 // Offset per transformIndex
922 transformStart_.setSize(nTrafo);
923 transformElements_.setSize(nTrafo);
924 forAll(transformStart_, trafoI)
926 transformStart_[trafoI] = constructSize_;
927 constructSize_ += nPerTransform[trafoI];
928 transformElements_[trafoI].setSize(nPerTransform[trafoI]);
931 // Sort transformed elements into their new slot.
934 transformedIndices.setSize(transformedElements.size());
935 forAll(transformedElements, i)
937 labelPair elem = transformedElements[i];
938 label procI = globalIndexAndTransform::processor(elem);
939 label index = globalIndexAndTransform::index(elem);
940 label trafoI = globalIndexAndTransform::transformIndex(elem);
942 // Get compact index for untransformed element
945 procI == Pstream::myProcNo()
947 : compactMap[procI][index]
950 label& n = nPerTransform[trafoI];
951 // index of element to transform
952 transformElements_[trafoI][n] = rawElemI;
953 // destination of transformed element
954 transformedIndices[i] = transformStart_[trafoI]+n;
965 Foam::mapDistribute::mapDistribute
967 const globalIndex& globalNumbering,
968 labelListList& cellCells,
969 const globalIndexAndTransform& globalTransforms,
970 const List<labelPairList>& transformedElements,
971 labelListList& transformedIndices,
972 List<Map<label> >& compactMap
978 // Construct per processor compact addressing of the global elements
979 // needed. The ones from the local processor are not included since
980 // these are always all needed.
981 calcCompactAddressing
988 // Add all (non-local) transformed elements needed.
989 forAll(transformedElements, cellI)
991 const labelPairList& elems = transformedElements[cellI];
995 label procI = globalIndexAndTransform::processor(elems[i]);
996 if (procI != Pstream::myProcNo())
998 label index = globalIndexAndTransform::index(elems[i]);
999 label nCompact = compactMap[procI].size();
1000 compactMap[procI].insert(index, nCompact);
1006 // Exchange what I need with processor that supplies it. Renumber elements
1007 // into compact numbering
1008 labelList compactStart;
1018 // Renumber the transformed elements
1019 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1020 // Count per transformIndex
1021 label nTrafo = globalTransforms.transformPermutations().size();
1022 labelList nPerTransform(nTrafo, 0);
1023 forAll(transformedElements, cellI)
1025 const labelPairList& elems = transformedElements[cellI];
1029 label trafoI = globalIndexAndTransform::transformIndex(elems[i]);
1030 nPerTransform[trafoI]++;
1033 // Offset per transformIndex
1034 transformStart_.setSize(nTrafo);
1035 transformElements_.setSize(nTrafo);
1036 forAll(transformStart_, trafoI)
1038 transformStart_[trafoI] = constructSize_;
1039 constructSize_ += nPerTransform[trafoI];
1040 transformElements_[trafoI].setSize(nPerTransform[trafoI]);
1043 // Sort transformed elements into their new slot.
1046 transformedIndices.setSize(transformedElements.size());
1047 forAll(transformedElements, cellI)
1049 const labelPairList& elems = transformedElements[cellI];
1050 transformedIndices[cellI].setSize(elems.size());
1054 label procI = globalIndexAndTransform::processor(elems[i]);
1055 label index = globalIndexAndTransform::index(elems[i]);
1056 label trafoI = globalIndexAndTransform::transformIndex(elems[i]);
1058 // Get compact index for untransformed element
1061 procI == Pstream::myProcNo()
1063 : compactMap[procI][index]
1066 label& n = nPerTransform[trafoI];
1067 // index of element to transform
1068 transformElements_[trafoI][n] = rawElemI;
1069 // destination of transformed element
1070 transformedIndices[cellI][i] = transformStart_[trafoI]+n;
1082 Foam::mapDistribute::mapDistribute(const mapDistribute& map)
1084 constructSize_(map.constructSize_),
1085 subMap_(map.subMap_),
1086 constructMap_(map.constructMap_),
1087 transformElements_(map.transformElements_),
1088 transformStart_(map.transformStart_),
1093 Foam::mapDistribute::mapDistribute(const Xfer<mapDistribute>& map)
1095 constructSize_(map().constructSize_),
1096 subMap_(map().subMap_.xfer()),
1097 constructMap_(map().constructMap_.xfer()),
1098 transformElements_(map().transformElements_.xfer()),
1099 transformStart_(map().transformStart_.xfer()),
1104 // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
1106 Foam::label Foam::mapDistribute::whichTransform(const label index) const
1108 return findLower(transformStart_, index+1);
1112 void Foam::mapDistribute::transfer(mapDistribute& rhs)
1114 constructSize_ = rhs.constructSize_;
1115 subMap_.transfer(rhs.subMap_);
1116 constructMap_.transfer(rhs.constructMap_);
1117 transformElements_.transfer(rhs.transformElements_);
1118 transformStart_.transfer(rhs.transformStart_);
1119 schedulePtr_.clear();
1123 Foam::Xfer<Foam::mapDistribute> Foam::mapDistribute::xfer()
1125 return xferMove(*this);
1129 Foam::label Foam::mapDistribute::renumber
1131 const globalIndex& globalNumbering,
1132 const List<Map<label> >& compactMap,
1140 if (globalNumbering.isLocal(globalI))
1142 return globalNumbering.toLocal(globalI);
1146 label procI = globalNumbering.whichProcID(globalI);
1147 label index = globalNumbering.toLocal(procI, globalI);
1148 return compactMap[procI][index];
1153 void Foam::mapDistribute::compact(const boolList& elemIsUsed)
1155 // 1. send back to sender. Have sender delete the corresponding element
1156 // from the submap and do the same to the constructMap locally
1157 // (and in same order).
1159 // Send elemIsUsed field to neighbour. Use nonblocking code from
1160 // mapDistribute but in reverse order.
1161 if (Pstream::parRun())
1163 List<boolList> sendFields(Pstream::nProcs());
1165 for (label domain = 0; domain < Pstream::nProcs(); domain++)
1167 const labelList& map = constructMap_[domain];
1169 if (domain != Pstream::myProcNo() && map.size())
1171 boolList& subField = sendFields[domain];
1172 subField.setSize(map.size());
1175 subField[i] = elemIsUsed[map[i]];
1180 Pstream::nonBlocking,
1182 reinterpret_cast<const char*>(subField.begin()),
1183 subField.size()*sizeof(bool)
1188 // Set up receives from neighbours
1190 List<boolList> recvFields(Pstream::nProcs());
1192 for (label domain = 0; domain < Pstream::nProcs(); domain++)
1194 const labelList& map = subMap_[domain];
1196 if (domain != Pstream::myProcNo() && map.size())
1198 recvFields[domain].setSize(map.size());
1201 Pstream::nonBlocking,
1203 reinterpret_cast<char*>(recvFields[domain].begin()),
1204 recvFields[domain].size()*sizeof(bool)
1210 // Set up 'send' to myself - write directly into recvFields
1213 const labelList& map = constructMap_[Pstream::myProcNo()];
1215 recvFields[Pstream::myProcNo()].setSize(map.size());
1218 recvFields[Pstream::myProcNo()][i] = elemIsUsed[map[i]];
1223 // Wait for all to finish
1225 Pstream::waitRequests();
1228 // Compact out all submap entries that are referring to unused elements
1229 for (label domain = 0; domain < Pstream::nProcs(); domain++)
1231 const labelList& map = subMap_[domain];
1233 labelList newMap(map.size());
1238 if (recvFields[domain][i])
1240 // So element is used on destination side
1241 newMap[newI++] = map[i];
1244 if (newI < map.size())
1246 newMap.setSize(newI);
1247 subMap_[domain].transfer(newMap);
1253 // 2. remove from construct map - since end-result (element in elemIsUsed)
1256 label maxConstructIndex = -1;
1258 for (label domain = 0; domain < Pstream::nProcs(); domain++)
1260 const labelList& map = constructMap_[domain];
1262 labelList newMap(map.size());
1267 label destinationI = map[i];
1269 // Is element is used on destination side
1270 if (elemIsUsed[destinationI])
1272 maxConstructIndex = max(maxConstructIndex, destinationI);
1274 newMap[newI++] = destinationI;
1277 if (newI < map.size())
1279 newMap.setSize(newI);
1280 constructMap_[domain].transfer(newMap);
1284 constructSize_ = maxConstructIndex+1;
1286 // Clear the schedule (note:not necessary if nothing changed)
1287 schedulePtr_.clear();
1291 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
1293 void Foam::mapDistribute::operator=(const mapDistribute& rhs)
1295 // Check for assignment to self
1300 "Foam::mapDistribute::operator=(const Foam::mapDistribute&)"
1301 ) << "Attempted assignment to self"
1302 << abort(FatalError);
1304 constructSize_ = rhs.constructSize_;
1305 subMap_ = rhs.subMap_;
1306 constructMap_ = rhs.constructMap_;
1307 transformElements_ = rhs.transformElements_;
1308 transformStart_ = rhs.transformStart_;
1309 schedulePtr_.clear();
1313 // ************************************************************************* //