1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | foam-extend: Open Source CFD
4 \\ / O peration | Version: 3.2
5 \\ / A nd | Web: http://www.foam-extend.org
6 \\/ M anipulation | For copyright notice see file Copyright
7 -------------------------------------------------------------------------------
9 This file is part of foam-extend.
11 foam-extend is free software: you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation, either version 3 of the License, or (at your
14 option) any later version.
16 foam-extend is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with foam-extend. If not, see <http://www.gnu.org/licenses/>.
24 \*---------------------------------------------------------------------------*/
26 #include "globalPoints.H"
27 #include "processorPolyPatch.H"
28 #include "cyclicPolyPatch.H"
31 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
33 defineTypeNameAndDebug(Foam::globalPoints, 0);
36 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
38 // Total number of points on processor patches. Is upper limit for number
40 Foam::label Foam::globalPoints::countPatchPoints
42 const polyBoundaryMesh& patches
47 forAll(patches, patchI)
49 const polyPatch& pp = patches[patchI];
53 (Pstream::parRun() && isA<processorPolyPatch>(pp))
54 || isA<cyclicPolyPatch>(pp)
57 nTotPoints += pp.nPoints();
65 // Collect all topological information about a point on a patch.
66 // (this information is the patch faces using the point and the relative
67 // position of the point in the face)
68 void Foam::globalPoints::addToSend
70 const primitivePatch& pp,
71 const label patchPointI,
72 const procPointList& knownInfo,
74 DynamicList<label>& patchFaces,
75 DynamicList<label>& indexInFace,
76 DynamicList<procPointList>& allInfo
79 label meshPointI = pp.meshPoints()[patchPointI];
81 // Add all faces using the point so we are sure we find it on the
83 const labelList& pFaces = pp.pointFaces()[patchPointI];
87 label patchFaceI = pFaces[i];
89 const face& f = pp[patchFaceI];
91 patchFaces.append(patchFaceI);
92 indexInFace.append(findIndex(f, meshPointI));
93 allInfo.append(knownInfo);
98 // Add nbrInfo to myInfo. Return true if anything changed.
99 // nbrInfo is for a point a list of all the processors using it (and the
100 // meshPoint label on that processor)
101 bool Foam::globalPoints::mergeInfo
103 const procPointList& nbrInfo,
104 procPointList& myInfo
107 // Indices of entries in nbrInfo not yet in myInfo.
108 DynamicList<label> newInfo(nbrInfo.size());
112 const procPoint& info = nbrInfo[i];
114 // Check if info already in myInfo.
119 if (myInfo[j] == info)
121 // Already have information for processor/point combination
122 // in my list so skip.
131 // Mark this information as being not yet in myInfo
138 // Append all nbrInfos referenced in newInfo to myInfo.
140 label index = myInfo.size();
142 myInfo.setSize(index + newInfo.size());
146 myInfo[index++] = nbrInfo[newInfo[i]];
149 // Did anything change?
150 return newInfo.size() > 0;
154 // Updates database of current information on meshpoints with nbrInfo.
155 // Uses mergeInfo above. Returns true if data kept for meshPointI changed.
156 bool Foam::globalPoints::storeInfo
158 const procPointList& nbrInfo,
159 const label meshPointI
162 label infoChanged = false;
164 // Get the index into the procPoints list.
165 Map<label>::iterator iter = meshToProcPoint_.find(meshPointI);
167 if (iter != meshToProcPoint_.end())
169 procPointList& knownInfo = procPoints_[iter()];
171 if (mergeInfo(nbrInfo, knownInfo))
178 procPointList knownInfo(1);
179 knownInfo[0][0] = Pstream::myProcNo();
180 knownInfo[0][1] = meshPointI;
182 if (mergeInfo(nbrInfo, knownInfo))
184 // Update addressing from into procPoints
185 meshToProcPoint_.insert(meshPointI, procPoints_.size());
186 // Insert into list of equivalences.
187 procPoints_.append(knownInfo);
196 // Insert my own points into structure and mark as changed.
197 void Foam::globalPoints::initOwnPoints
199 const bool allPoints,
200 labelHashSet& changedPoints
203 const polyBoundaryMesh& patches = mesh_.boundaryMesh();
205 forAll(patches, patchI)
207 const polyPatch& pp = patches[patchI];
211 (Pstream::parRun() && isA<processorPolyPatch>(pp))
212 || isA<cyclicPolyPatch>(pp)
215 const labelList& meshPoints = pp.meshPoints();
219 // All points on patch
220 forAll(meshPoints, i)
222 label meshPointI = meshPoints[i];
224 procPointList knownInfo(1);
225 knownInfo[0][0] = Pstream::myProcNo();
226 knownInfo[0][1] = meshPointI;
228 // Update addressing from meshpoint to index in procPoints
229 meshToProcPoint_.insert(meshPointI, procPoints_.size());
230 // Insert into list of equivalences.
231 procPoints_.append(knownInfo);
233 // Update changedpoints info.
234 changedPoints.insert(meshPointI);
239 // Boundary points only
240 const labelList& boundaryPoints = pp.boundaryPoints();
242 forAll(boundaryPoints, i)
244 label meshPointI = meshPoints[boundaryPoints[i]];
246 procPointList knownInfo(1);
247 knownInfo[0][0] = Pstream::myProcNo();
248 knownInfo[0][1] = meshPointI;
250 // Update addressing from meshpoint to index in procPoints
251 meshToProcPoint_.insert(meshPointI, procPoints_.size());
252 // Insert into list of equivalences.
253 procPoints_.append(knownInfo);
255 // Update changedpoints info.
256 changedPoints.insert(meshPointI);
264 // Send all my info on changedPoints_ to my neighbours.
265 void Foam::globalPoints::sendPatchPoints(const labelHashSet& changedPoints)
268 const polyBoundaryMesh& patches = mesh_.boundaryMesh();
270 forAll(patches, patchI)
272 const polyPatch& pp = patches[patchI];
274 if (Pstream::parRun() && isA<processorPolyPatch>(pp))
276 // Information to send:
278 DynamicList<label> patchFaces(pp.nPoints());
279 // index in patch face
280 DynamicList<label> indexInFace(pp.nPoints());
281 // all information I currently hold about this patchPoint
282 DynamicList<procPointList> allInfo(pp.nPoints());
285 // Now collect information on all mesh points mentioned in
286 // changedPoints. Note that these points only should occur on
287 // processorPatches (or rather this is a limitation!).
289 const labelList& meshPoints = pp.meshPoints();
291 forAll(meshPoints, patchPointI)
293 label meshPointI = meshPoints[patchPointI];
295 if (changedPoints.found(meshPointI))
297 label index = meshToProcPoint_[meshPointI];
299 const procPointList& knownInfo = procPoints_[index];
301 // Add my information about meshPointI to the send buffers
315 indexInFace.shrink();
320 const processorPolyPatch& procPatch =
321 refCast<const processorPolyPatch>(pp);
325 Pout<< " Sending to "
326 << procPatch.neighbProcNo() << " point information:"
327 << patchFaces.size() << endl;
333 procPatch.neighbProcNo()
336 toNeighbour << patchFaces << indexInFace << allInfo;
343 // Receive all my neighbours' information and merge with mine.
344 // After finishing will have updated
345 // - procPoints_ : all neighbour information merged in.
346 // - meshToProcPoint_
347 // - changedPoints: all meshPoints for which something changed.
348 void Foam::globalPoints::receivePatchPoints(labelHashSet& changedPoints)
350 const polyBoundaryMesh& patches = mesh_.boundaryMesh();
352 // Reset changed points
353 changedPoints.clear();
355 forAll(patches, patchI)
357 const polyPatch& pp = patches[patchI];
359 if (Pstream::parRun() && isA<processorPolyPatch>(pp))
361 const processorPolyPatch& procPatch =
362 refCast<const processorPolyPatch>(pp);
364 labelList patchFaces;
365 labelList indexInFace;
366 List<procPointList> nbrInfo;
369 IPstream fromNeighbour
372 procPatch.neighbProcNo()
374 fromNeighbour >> patchFaces >> indexInFace >> nbrInfo;
379 Pout<< " Received from "
380 << procPatch.neighbProcNo() << " point information:"
381 << patchFaces.size() << endl;
384 forAll(patchFaces, i)
386 const face& f = pp[patchFaces[i]];
388 // Get index in this face from index on face on other side.
389 label index = (f.size() - indexInFace[i]) % f.size();
391 // Get the meshpoint on my side
392 label meshPointI = f[index];
394 //const procPointList& info = nbrInfo[i];
395 //Pout << "Received for my coord "
396 // << mesh_.points()[meshPointI];
400 // Pout<< ' ' <<info[j];
404 if (storeInfo(nbrInfo[i], meshPointI))
406 changedPoints.insert(meshPointI);
410 else if (isA<cyclicPolyPatch>(pp))
412 // Handle cyclics: send lower half to upper half and vice versa.
413 // Or since they both are in memory just do it point by point.
415 const cyclicPolyPatch& cycPatch =
416 refCast<const cyclicPolyPatch>(pp);
418 const labelList& meshPoints = pp.meshPoints();
420 //const edgeList& connections = cycPatch.coupledPoints();
421 const edgeList connections(coupledPoints(cycPatch));
423 forAll(connections, i)
425 const edge& e = connections[i];
427 label meshPointA = meshPoints[e[0]];
428 label meshPointB = meshPoints[e[1]];
430 // Do we have information on meshPointA?
431 Map<label>::iterator procPointA =
432 meshToProcPoint_.find(meshPointA);
434 if (procPointA != meshToProcPoint_.end())
436 // Store A info onto pointB
437 if (storeInfo(procPoints_[procPointA()], meshPointB))
439 changedPoints.insert(meshPointB);
443 // Same for info on pointB
444 Map<label>::iterator procPointB =
445 meshToProcPoint_.find(meshPointB);
447 if (procPointB != meshToProcPoint_.end())
449 // Store B info onto pointA
450 if (storeInfo(procPoints_[procPointB()], meshPointA))
452 changedPoints.insert(meshPointA);
461 // Remove entries which are handled by normal face-face communication. I.e.
462 // those points where the equivalence list is only me and my (face)neighbour
463 void Foam::globalPoints::remove(const Map<label>& directNeighbours)
466 Map<label> oldMeshToProcPoint(meshToProcPoint_);
467 meshToProcPoint_.clear();
469 List<procPointList> oldProcPoints;
470 oldProcPoints.transfer(procPoints_);
472 // Go through all equivalences
475 Map<label>::const_iterator iter = oldMeshToProcPoint.begin();
476 iter != oldMeshToProcPoint.end();
480 label meshPointI = iter.key();
481 const procPointList& pointInfo = oldProcPoints[iter()];
483 if (pointInfo.size() == 2)
485 // I will be in this equivalence list.
486 // Check whether my direct (=face) neighbour
487 // is in it. This would be an ordinary connection and can be
488 // handled by normal face-face connectivity.
490 const procPoint& a = pointInfo[0];
491 const procPoint& b = pointInfo[1];
495 (a[0] == Pstream::myProcNo() && directNeighbours.found(a[1]))
496 || (b[0] == Pstream::myProcNo() && directNeighbours.found(b[1]))
499 // Normal faceNeighbours
500 if (a[0] == Pstream::myProcNo())
502 //Pout<< "Removing direct neighbour:"
503 // << mesh_.points()[a[1]]
506 else if (b[0] == Pstream::myProcNo())
508 //Pout<< "Removing direct neighbour:"
509 // << mesh_.points()[b[1]]
515 // This condition will be very rare: points are used by
516 // two processors which are not face-face connected.
523 // Processor A and B share a point. Note that this only will
524 // be found if the two domains are face connected at all
525 // (not shown in the picture)
527 meshToProcPoint_.insert(meshPointI, procPoints_.size());
528 procPoints_.append(pointInfo);
531 else if (pointInfo.size() == 1)
533 // This happens for 'wedge' like cyclics where the two halves
534 // come together in the same point so share the same meshPoint.
535 // So this meshPoint will have info of size one only.
538 pointInfo[0][0] != Pstream::myProcNo()
539 || !directNeighbours.found(pointInfo[0][1])
542 meshToProcPoint_.insert(meshPointI, procPoints_.size());
543 procPoints_.append(pointInfo);
548 meshToProcPoint_.insert(meshPointI, procPoints_.size());
549 procPoints_.append(pointInfo);
553 procPoints_.shrink();
557 // Get (indices of) points for which I am master (= lowest numbered point on
558 // lowest numbered processor).
559 // (equivalence lists should be complete by now)
560 Foam::labelList Foam::globalPoints::getMasterPoints() const
562 labelList masterPoints(nPatchPoints_);
565 // Go through all equivalences and determine meshPoints where I am master.
568 Map<label>::const_iterator iter = meshToProcPoint_.begin();
569 iter != meshToProcPoint_.end();
573 label meshPointI = iter.key();
574 const procPointList& pointInfo = procPoints_[iter()];
576 if (pointInfo.size() < 2)
578 // Points should have an equivalence list >= 2 since otherwise
579 // they would be direct neighbours and have been removed in the
581 Pout<< "MeshPoint:" << meshPointI
582 << " coord:" << mesh_.points()[meshPointI]
583 << " has no corresponding point on a neighbouring processor"
585 FatalErrorIn("globalPoints::getMasterPoints()")
586 << '[' << Pstream::myProcNo() << ']'
587 << " MeshPoint:" << meshPointI
588 << " coord:" << mesh_.points()[meshPointI]
589 << " has no corresponding point on a neighbouring processor"
590 << abort(FatalError);
594 // Find lowest processor and lowest mesh point on this processor.
595 label lowestProcI = labelMax;
596 label lowestPointI = labelMax;
600 label proc = pointInfo[i][0];
602 if (proc < lowestProcI)
605 lowestPointI = pointInfo[i][1];
607 else if (proc == lowestProcI)
609 lowestPointI = min(lowestPointI, pointInfo[i][1]);
615 lowestProcI == Pstream::myProcNo()
616 && lowestPointI == meshPointI
619 // I am lowest numbered processor and point. Add to my list.
620 masterPoints[nMaster++] = meshPointI;
625 masterPoints.setSize(nMaster);
631 // Send subset of lists
632 void Foam::globalPoints::sendSharedPoints(const labelList& changedIndices) const
634 const polyBoundaryMesh& patches = mesh_.boundaryMesh();
636 forAll(patches, patchI)
638 const polyPatch& pp = patches[patchI];
640 if (Pstream::parRun() && isA<processorPolyPatch>(pp))
642 const processorPolyPatch& procPatch =
643 refCast<const processorPolyPatch>(pp);
645 OPstream toNeighbour(Pstream::blocking, procPatch.neighbProcNo());
649 Pout<< "Sending to " << procPatch.neighbProcNo()
650 << " changed sharedPoints info:"
651 << changedIndices.size() << endl;
655 << UIndirectList<label>(sharedPointAddr_, changedIndices)()
656 << UIndirectList<label>(sharedPointLabels_, changedIndices)();
662 // Receive shared point indices for all my shared points. Note that since
663 // there are only a few here we can build a reverse map using the meshpoint
664 // instead of doing all this relative point indexing (patch face + index in
665 // face) as in send/receivePatchPoints
666 void Foam::globalPoints::receiveSharedPoints(labelList& changedIndices)
668 changedIndices.setSize(sharedPointAddr_.size());
671 const polyBoundaryMesh& patches = mesh_.boundaryMesh();
673 // Receive and set shared points
674 forAll(patches, patchI)
676 const polyPatch& pp = patches[patchI];
678 if (Pstream::parRun() && isA<processorPolyPatch>(pp))
680 const processorPolyPatch& procPatch =
681 refCast<const processorPolyPatch>(pp);
683 // Map from neighbouring meshPoint to sharedPoint)
684 Map<label> nbrSharedPoints(sharedPointAddr_.size());
687 // Receive meshPoints on neighbour and sharedPoints and build
688 // map from it. Note that we could have built the map on the
689 // neighbour and sent it over.
690 labelList nbrSharedPointAddr;
691 labelList nbrSharedPointLabels;
694 IPstream fromNeighbour
697 procPatch.neighbProcNo()
699 fromNeighbour >> nbrSharedPointAddr >> nbrSharedPointLabels;
702 // Insert into to map
703 forAll(nbrSharedPointLabels, i)
705 nbrSharedPoints.insert
707 nbrSharedPointLabels[i], // meshpoint on neighbour
708 nbrSharedPointAddr[i] // sharedPoint label
714 // Merge into whatever information I hold.
717 Map<label>::const_iterator iter = meshToProcPoint_.begin();
718 iter != meshToProcPoint_.end();
722 label meshPointI = iter.key();
723 label index = iter();
725 if (sharedPointAddr_[index] == -1)
727 // No shared point known yet for this meshPoint.
728 // See if was received from neighbour.
729 const procPointList& knownInfo = procPoints_[index];
731 // Check through the whole equivalence list for any
732 // point from the neighbour.
735 const procPoint& info = knownInfo[j];
739 (info[0] == procPatch.neighbProcNo())
740 && nbrSharedPoints.found(info[1])
743 // So this knownInfo contains the neighbour point
744 label sharedPointI = nbrSharedPoints[info[1]];
746 sharedPointAddr_[index] = sharedPointI;
747 sharedPointLabels_[index] = meshPointI;
748 changedIndices[nChanged++] = index;
756 else if (isA<cyclicPolyPatch>(pp))
758 const cyclicPolyPatch& cycPatch =
759 refCast<const cyclicPolyPatch>(pp);
761 // Build map from meshPoint to sharedPoint
762 Map<label> meshToSharedPoint(sharedPointAddr_.size());
763 forAll(sharedPointLabels_, i)
765 label meshPointI = sharedPointLabels_[i];
767 meshToSharedPoint.insert(meshPointI, sharedPointAddr_[i]);
771 //const edgeList& connections = cycPatch.coupledPoints();
772 const edgeList connections(coupledPoints(cycPatch));
774 forAll(connections, i)
776 const edge& e = connections[i];
778 label meshPointA = pp.meshPoints()[e[0]];
779 label meshPointB = pp.meshPoints()[e[1]];
781 // Do we already have shared point for meshPointA?
782 Map<label>::iterator fndA = meshToSharedPoint.find(meshPointA);
783 Map<label>::iterator fndB = meshToSharedPoint.find(meshPointB);
785 if (fndA != meshToSharedPoint.end())
787 if (fndB != meshToSharedPoint.end())
789 if (fndA() != fndB())
793 "globalPoints::receiveSharedPoints"
795 ) << "On patch " << pp.name()
796 << " connected points " << meshPointA
797 << ' ' << mesh_.points()[meshPointA]
798 << " and " << meshPointB
799 << ' ' << mesh_.points()[meshPointB]
800 << " are mapped to different shared points: "
801 << fndA() << " and " << fndB()
802 << abort(FatalError);
807 // No shared point yet for B.
808 label sharedPointI = fndA();
810 // Store shared point for meshPointB
811 label index = meshToProcPoint_[meshPointB];
813 sharedPointAddr_[index] = sharedPointI;
814 sharedPointLabels_[index] = meshPointB;
815 changedIndices[nChanged++] = index;
820 // No shared point yet for A.
821 if (fndB != meshToSharedPoint.end())
823 label sharedPointI = fndB();
825 // Store shared point for meshPointA
826 label index = meshToProcPoint_[meshPointA];
828 sharedPointAddr_[index] = sharedPointI;
829 sharedPointLabels_[index] = meshPointA;
830 changedIndices[nChanged++] = index;
837 changedIndices.setSize(nChanged);
841 Foam::edgeList Foam::globalPoints::coupledPoints(const cyclicPolyPatch& pp)
843 // Look at cyclic patch as two halves, A and B.
844 // Now all we know is that relative face index in halfA is same
845 // as coupled face in halfB and also that the 0th vertex
848 // From halfA point to halfB or -1.
849 labelList coupledPoint(pp.nPoints(), -1);
851 for (label patchFaceA = 0; patchFaceA < pp.size()/2; patchFaceA++)
853 const face& fA = pp.localFaces()[patchFaceA];
857 label patchPointA = fA[indexA];
859 if (coupledPoint[patchPointA] == -1)
861 const face& fB = pp.localFaces()[patchFaceA + pp.size()/2];
863 label indexB = (fB.size() - indexA) % fB.size();
865 coupledPoint[patchPointA] = fB[indexB];
870 edgeList connected(pp.nPoints());
872 // Extract coupled points.
873 label connectedI = 0;
875 forAll(coupledPoint, i)
877 if (coupledPoint[i] != -1)
879 connected[connectedI++] = edge(i, coupledPoint[i]);
883 connected.setSize(connectedI);
889 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
891 // Construct from components
892 Foam::globalPoints::globalPoints(const polyMesh& mesh)
895 nPatchPoints_(countPatchPoints(mesh.boundaryMesh())),
896 procPoints_(nPatchPoints_),
897 meshToProcPoint_(nPatchPoints_),
899 sharedPointLabels_(0),
904 Pout<< "globalPoints::globalPoints(const polyMesh&) : "
905 << "doing processor to processor communication to get sharedPoints"
909 labelHashSet changedPoints(nPatchPoints_);
911 // Initialize procPoints with my patch points. Keep track of points
912 // inserted (in changedPoints)
913 // There are two possible forms of this:
914 // - initialize with all patch points (allPoints = true). This causes all
915 // patch points to be exchanged so a lot of information gets stored and
916 // transferred. This all gets filtered out later when removing the
917 // equivalence lists of size 2.
918 // - initialize with boundary points of patches only (allPoints = false).
919 // This should work for all decompositions except extreme ones where a
920 // shared point is not on the boundary of any processor patches using it.
921 // This would happen if a domain was pinched such that two patches share
923 initOwnPoints(true, changedPoints);
925 // Do one exchange iteration to get neighbour points.
926 sendPatchPoints(changedPoints);
927 receivePatchPoints(changedPoints);
930 // Save neighbours reachable through face-face communication.
931 Map<label> neighbourList(meshToProcPoint_);
934 // Exchange until nothing changes on all processors.
935 bool changed = false;
939 sendPatchPoints(changedPoints);
940 receivePatchPoints(changedPoints);
942 changed = changedPoints.size() > 0;
943 reduce(changed, orOp<bool>());
948 // Remove direct neighbours from point equivalences.
949 remove(neighbourList);
952 //Pout<< "After removing locally connected points:" << endl;
955 // Map<label>::const_iterator iter = meshToProcPoint_.begin();
956 // iter != meshToProcPoint_.end();
960 // label meshPointI = iter.key();
961 // const procPointList& pointInfo = procPoints_[iter()];
963 // forAll(pointInfo, i)
965 // Pout<< " pointI:" << meshPointI << ' '
966 // << mesh.points()[meshPointI]
967 // << " connected to proc " << pointInfo[i][0]
968 // << " point:" << pointInfo[i][1]
974 // We now have - in procPoints_ - a list of points which are shared between
975 // multiple processors. These are the ones for which are sharedPoint
976 // needs to be determined. This is done by having the lowest numbered
977 // processor in the equivalence list 'ask' for a sharedPoint number
978 // and then distribute it across processor patches to the non-master
979 // processors. Note: below piece of coding is not very efficient. Uses
980 // a Map where possibly it shouldn't
982 // Initialize sharedPoint addressing. Is for every entry in procPoints_
984 sharedPointAddr_.setSize(meshToProcPoint_.size());
985 sharedPointAddr_ = -1;
986 sharedPointLabels_.setSize(meshToProcPoint_.size());
987 sharedPointLabels_ = -1;
990 // Get points for which I am master (lowest numbered proc)
991 labelList masterPoints(getMasterPoints());
994 // Determine number of master points on all processors.
995 labelList sharedPointSizes(Pstream::nProcs());
996 sharedPointSizes[Pstream::myProcNo()] = masterPoints.size();
998 Pstream::gatherList(sharedPointSizes);
999 Pstream::scatterList(sharedPointSizes);
1003 Pout<< "sharedPointSizes:" << sharedPointSizes << endl;
1006 // Get total number of shared points
1008 forAll(sharedPointSizes, procI)
1010 nGlobalPoints_ += sharedPointSizes[procI];
1013 // Assign sharedPoint labels. Every processor gets assigned consecutive
1014 // numbers for its master points.
1015 // These are assigned in processor order so processor0 gets
1016 // 0..masterPoints.size()-1 etc.
1018 // My point labels start after those of lower numbered processors
1019 label sharedPointI = 0;
1020 for (label procI = 0; procI < Pstream::myProcNo(); procI++)
1022 sharedPointI += sharedPointSizes[procI];
1025 forAll(masterPoints, i)
1027 label meshPointI = masterPoints[i];
1029 label index = meshToProcPoint_[meshPointI];
1031 sharedPointLabels_[index] = meshPointI;
1032 sharedPointAddr_[index] = sharedPointI++;
1036 // Now we have a sharedPointLabel for some of the entries in procPoints.
1037 // Send this information to neighbours. Receive their information.
1038 // Loop until nothing changes.
1040 // Initial subset to send is points for which I have sharedPoints
1041 labelList changedIndices(sharedPointAddr_.size());
1044 forAll(sharedPointAddr_, i)
1046 if (sharedPointAddr_[i] != -1)
1048 changedIndices[nChanged++] = i;
1051 changedIndices.setSize(nChanged);
1059 Pout<< "Determined " << changedIndices.size() << " shared points."
1060 << " Exchanging them" << endl;
1062 sendSharedPoints(changedIndices);
1063 receiveSharedPoints(changedIndices);
1065 changed = changedIndices.size() > 0;
1066 reduce(changed, orOp<bool>());
1071 forAll(sharedPointLabels_, i)
1073 if (sharedPointLabels_[i] == -1)
1075 FatalErrorIn("globalPoints::globalPoints(const polyMesh& mesh)")
1076 << "Problem: shared point on processor " << Pstream::myProcNo()
1077 << " not set at index " << sharedPointLabels_[i] << endl
1078 << "This might mean the individual processor domains are not"
1079 << " connected and the overall domain consists of multiple"
1080 << " regions. You can check this with checkMesh"
1081 << abort(FatalError);
1087 Pout<< "globalPoints::globalPoints(const polyMesh&) : "
1088 << "Finished global points" << endl;
1093 // ************************************************************************* //