globalPoints.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2021 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
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.
15 
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
19  for more details.
20 
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/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "globalPoints.H"
27 #include "processorPolyPatch.H"
28 #include "cyclicPolyPatch.H"
29 #include "polyMesh.H"
30 #include "mapDistribute.H"
31 
32 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
33 
34 namespace Foam
35 {
36  defineTypeNameAndDebug(globalPoints, 0);
37 }
38 
39 
40 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
41 
42 Foam::label Foam::globalPoints::countPatchPoints
43 (
44  const polyBoundaryMesh& patches
45 )
46 {
47  label nTotPoints = 0;
48 
49  forAll(patches, patchi)
50  {
51  const polyPatch& pp = patches[patchi];
52  if (pp.coupled())
53  {
54  nTotPoints += pp.nPoints();
55  }
56  }
57  return nTotPoints;
58 }
59 
60 
61 Foam::label Foam::globalPoints::findSamePoint
62 (
63  const labelPairList& allInfo,
64  const labelPair& info
65 ) const
66 {
67  const label proci = globalTransforms_.processor(info);
68  const label index = globalTransforms_.index(info);
69 
70  forAll(allInfo, i)
71  {
72  if
73  (
74  globalTransforms_.processor(allInfo[i]) == proci
75  && globalTransforms_.index(allInfo[i]) == index
76  )
77  {
78  return i;
79  }
80  }
81  return -1;
82 }
83 
84 
85 Foam::labelPairList Foam::globalPoints::addSendTransform
86 (
87  const label patchi,
88  const labelPairList& info
89 ) const
90 {
91  scalar tol = refCast<const coupledPolyPatch>
92  (
93  mesh_.boundaryMesh()[patchi]
94  ).matchTolerance();
95 
96  labelPairList sendInfo(info.size());
97 
98  forAll(info, i)
99  {
100  // Pout<< " adding send transform to" << nl
101  // << " proc:" << globalTransforms_.processor(info[i])
102  // << nl
103  // << " index:" << globalTransforms_.index(info[i]) << nl
104  // << " trafo:"
105  // << globalTransforms_.decodeTransformIndex
106  // (globalTransforms_.transformIndex(info[i]))
107  // << endl;
108 
109  sendInfo[i] = globalTransforms_.encode
110  (
111  globalTransforms_.processor(info[i]),
112  globalTransforms_.index(info[i]),
113  globalTransforms_.addToTransformIndex
114  (
115  globalTransforms_.transformIndex(info[i]),
116  patchi,
117  true, // patchi is sending side
118  tol // tolerance for comparison
119  )
120  );
121  }
122  return sendInfo;
123 }
124 
125 
126 void Foam::globalPoints::addToSend
127 (
128  const polyPatch& pp,
129  const label patchPointi,
130  const labelPairList& knownInfo,
131 
132  DynamicList<label>& patchFaces,
133  DynamicList<label>& indexInFace,
134  DynamicList<labelPairList>& allInfo
135 ) const
136 {
137  // Collect all topological information about a point on a patch. (this
138  // information is the patch faces using the point and the relative position
139  // of the point in the face)
140 
141  label meshPointi = pp.meshPoints()[patchPointi];
142 
143  // Add all faces using the point so we are sure we find it on the
144  // other side.
145  const labelList& pFaces = pp.pointFaces()[patchPointi];
146 
147  forAll(pFaces, i)
148  {
149  label patchFacei = pFaces[i];
150 
151  const face& f = pp[patchFacei];
152 
153  patchFaces.append(patchFacei);
154  indexInFace.append(findIndex(f, meshPointi));
155 
156  // Add patch transformation
157  allInfo.append(addSendTransform(pp.index(), knownInfo));
158  }
159 }
160 
161 
162 bool Foam::globalPoints::mergeInfo
163 (
164  const labelPairList& nbrInfo,
165  const label localPointi,
166  labelPairList& myInfo
167 ) const
168 {
169  // Add nbrInfo to myInfo. Return true if anything changed. nbrInfo is for a
170  // point a list of all the global points using it
171 
172  bool anyChanged = false;
173 
174  // Extend to make space for the nbrInfo (trimmed later)
175  labelPairList newInfo(myInfo);
176  label newI = newInfo.size();
177  newInfo.setSize(newI + nbrInfo.size());
178 
179  forAll(nbrInfo, i)
180  {
181  // Check if already have information about nbr point. There are two
182  // possibilities:
183  // - information found about same point but different transform.
184  // Combine transforms
185  // - information not found.
186 
187  label index = findSamePoint(myInfo, nbrInfo[i]);
188 
189  if (index == -1)
190  {
191  // New point
192  newInfo[newI++] = nbrInfo[i];
193  anyChanged = true;
194  }
195  else
196  {
197  // Same point. So we already have a connection between localPointi
198  // and the nbrIndex. Two situations:
199  // - same transform
200  // - one transform takes two steps, the other just a single.
201  if (myInfo[index] == nbrInfo[i])
202  {
203  // Everything same (so also transform). Nothing changed.
204  }
205  else
206  {
207  label myTransform = globalTransforms_.transformIndex
208  (
209  myInfo[index]
210  );
211  label nbrTransform = globalTransforms_.transformIndex
212  (
213  nbrInfo[i]
214  );
215 
216  // Different transform. See which is 'simplest'.
217  label minTransform = globalTransforms_.minimumTransformIndex
218  (
219  myTransform,
220  nbrTransform
221  );
222 
223  if (minTransform != myTransform)
224  {
225  // Use nbr info.
226  newInfo[index] = nbrInfo[i];
227  anyChanged = true;
228  }
229  }
230  }
231  }
232 
233  newInfo.setSize(newI);
234  myInfo.transfer(newInfo);
235 
236  return anyChanged;
237 }
238 
239 
240 Foam::label Foam::globalPoints::meshToLocalPoint
241 (
242  const Map<label>& meshToPatchPoint, // from mesh point to local numbering
243  const label meshPointi
244 )
245 {
246  return
247  (
248  meshToPatchPoint.size() == 0
249  ? meshPointi
250  : meshToPatchPoint[meshPointi]
251  );
252 }
253 
254 
255 Foam::label Foam::globalPoints::localToMeshPoint
256 (
257  const labelList& patchToMeshPoint,
258  const label localPointi
259 )
260 {
261  return
262  (
263  patchToMeshPoint.size() == 0
264  ? localPointi
265  : patchToMeshPoint[localPointi]
266  );
267 }
268 
269 
270 bool Foam::globalPoints::mergeInfo
271 (
272  const labelPairList& nbrInfo,
273  const label localPointi
274 )
275 {
276  // Updates database of current information on meshpoints with nbrInfo. Uses
277  // mergeInfo above. Returns true if data kept for meshPointi changed.
278 
279  label infoChanged = false;
280 
281  // Get the index into the procPoints list.
282  Map<label>::iterator iter = meshToProcPoint_.find(localPointi);
283 
284  if (iter != meshToProcPoint_.end())
285  {
286  if (mergeInfo(nbrInfo, localPointi, procPoints_[iter()]))
287  {
288  infoChanged = true;
289  }
290  }
291  else
292  {
293  // Construct local index for point
294  labelPairList knownInfo
295  (
296  1,
297  globalTransforms_.encode
298  (
300  localPointi,
301  globalTransforms_.nullTransformIndex()
302  )
303  );
304 
305  if (mergeInfo(nbrInfo, localPointi, knownInfo))
306  {
307  // Update addressing from into procPoints
308  meshToProcPoint_.insert(localPointi, procPoints_.size());
309  // Insert into list of equivalences.
310  procPoints_.append(knownInfo);
311 
312  infoChanged = true;
313  }
314  }
315  return infoChanged;
316 }
317 
318 
319 bool Foam::globalPoints::storeInitialInfo
320 (
321  const labelPairList& nbrInfo,
322  const label localPointi
323 )
324 {
325  // Updates database of current information on meshpoints with nbrInfo. Uses
326  // mergeInfo above. Returns true if data kept for meshPointi changed.
327 
328  label infoChanged = false;
329 
330  // Get the index into the procPoints list.
331  Map<label>::iterator iter = meshToProcPoint_.find(localPointi);
332 
333  if (iter != meshToProcPoint_.end())
334  {
335  if (mergeInfo(nbrInfo, localPointi, procPoints_[iter()]))
336  {
337  infoChanged = true;
338  }
339  }
340  else
341  {
342  // Update addressing into procPoints
343  meshToProcPoint_.insert(localPointi, procPoints_.size());
344  // Insert into list of equivalences.
345  procPoints_.append(nbrInfo);
346 
347  infoChanged = true;
348  }
349  return infoChanged;
350 }
351 
352 
353 void Foam::globalPoints::printProcPoint
354 (
355  const labelList& patchToMeshPoint,
356  const labelPair& pointInfo
357 ) const
358 {
359  label proci = globalTransforms_.processor(pointInfo);
360  label index = globalTransforms_.index(pointInfo);
361  label trafoI = globalTransforms_.transformIndex(pointInfo);
362 
363  Pout<< " proc:" << proci;
364  Pout<< " localpoint:";
365  Pout<< index;
366  Pout<< " through transform:"
367  << trafoI << " bits:"
368  << globalTransforms_.decodeTransformIndex(trafoI);
369 
370  if (proci == Pstream::myProcNo())
371  {
372  label meshPointi = localToMeshPoint(patchToMeshPoint, index);
373  Pout<< " at:" << mesh_.points()[meshPointi];
374  }
375 }
376 
377 
378 void Foam::globalPoints::printProcPoints
379 (
380  const labelList& patchToMeshPoint,
381  const labelPairList& pointInfo
382 ) const
383 {
384  forAll(pointInfo, i)
385  {
386  printProcPoint(patchToMeshPoint, pointInfo[i]);
387  Pout<< endl;
388  }
389 }
390 
391 
392 void Foam::globalPoints::initOwnPoints
393 (
394  const Map<label>& meshToPatchPoint,
395  const bool allPoints,
396  labelHashSet& changedPoints
397 )
398 {
399  const polyBoundaryMesh& patches = mesh_.boundaryMesh();
400 
401  forAll(patches, patchi)
402  {
403  const polyPatch& pp = patches[patchi];
404 
405  if (pp.coupled())
406  {
407  const labelList& meshPoints = pp.meshPoints();
408 
409  if (allPoints)
410  {
411  // All points on patch
412  forAll(meshPoints, patchPointi)
413  {
414  label meshPointi = meshPoints[patchPointi];
415  label localPointi = meshToLocalPoint
416  (
417  meshToPatchPoint,
418  meshPointi
419  );
420 
421  labelPairList knownInfo
422  (
423  1,
424  globalTransforms_.encode
425  (
427  localPointi,
428  globalTransforms_.nullTransformIndex()
429  )
430  );
431 
432  // Pout<< "For point "<< pp.points()[meshPointi]
433  // << " inserting info " << knownInfo
434  // << endl;
435 
436  // Update changedpoints info.
437  if (storeInitialInfo(knownInfo, localPointi))
438  {
439  changedPoints.insert(localPointi);
440  }
441  }
442  }
443  else
444  {
445  // Boundary points only
446  const labelList& boundaryPoints = pp.boundaryPoints();
447 
448  forAll(boundaryPoints, i)
449  {
450  label meshPointi = meshPoints[boundaryPoints[i]];
451  label localPointi = meshToLocalPoint
452  (
453  meshToPatchPoint,
454  meshPointi
455  );
456 
457  labelPairList knownInfo
458  (
459  1,
460  globalTransforms_.encode
461  (
463  localPointi,
464  globalTransforms_.nullTransformIndex()
465  )
466  );
467 
468  if (storeInitialInfo(knownInfo, localPointi))
469  {
470  changedPoints.insert(localPointi);
471  }
472  }
473  }
474  }
475  }
476 }
477 
478 
479 void Foam::globalPoints::sendPatchPoints
480 (
481  const bool mergeSeparated,
482  const Map<label>& meshToPatchPoint,
483  PstreamBuffers& pBufs,
484  const labelHashSet& changedPoints
485 ) const
486 {
487  const polyBoundaryMesh& patches = mesh_.boundaryMesh();
488  const labelPairList& patchInfo = globalTransforms_.patchTransformSign();
489 
490  forAll(patches, patchi)
491  {
492  const polyPatch& pp = patches[patchi];
493 
494  // mergeSeparated=true : send from all processor patches
495  // =false: send from ones without transform
496 
497  if
498  (
499  (Pstream::parRun() && isA<processorPolyPatch>(pp))
500  && (mergeSeparated || patchInfo[patchi].first() == -1)
501  )
502  {
503  const processorPolyPatch& procPatch =
504  refCast<const processorPolyPatch>(pp);
505 
506  // Information to send:
507  // patch face
508  DynamicList<label> patchFaces(pp.nPoints());
509  // index in patch face
510  DynamicList<label> indexInFace(pp.nPoints());
511  // all information I currently hold about this patchPoint
512  DynamicList<labelPairList> allInfo(pp.nPoints());
513 
514 
515  // Now collect information on all points mentioned in
516  // changedPoints. Note that these points only should occur on
517  // processorPatches (or rather this is a limitation!).
518 
519  const labelList& meshPoints = pp.meshPoints();
520 
521  forAll(meshPoints, patchPointi)
522  {
523  label meshPointi = meshPoints[patchPointi];
524  label localPointi = meshToLocalPoint
525  (
526  meshToPatchPoint,
527  meshPointi
528  );
529 
530  if (changedPoints.found(localPointi))
531  {
532  label index = meshToProcPoint_[localPointi];
533 
534  const labelPairList& knownInfo = procPoints_[index];
535 
536  // Add my information about localPointi to the
537  // send buffers. Encode the transformation
538  addToSend
539  (
540  pp,
541  patchPointi,
542  knownInfo,
543 
544  patchFaces,
545  indexInFace,
546  allInfo
547  );
548  }
549  }
550 
551  // Send to neighbour
552  if (debug)
553  {
554  Pout<< " Sending from " << pp.name() << " to "
555  << procPatch.neighbProcNo() << " point information:"
556  << patchFaces.size() << endl;
557  }
558 
559  UOPstream toNeighbour(procPatch.neighbProcNo(), pBufs);
560  toNeighbour << patchFaces << indexInFace << allInfo;
561  }
562  }
563 }
564 
565 
566 void Foam::globalPoints::receivePatchPoints
567 (
568  const bool mergeSeparated,
569  const Map<label>& meshToPatchPoint,
570  const labelList& patchToMeshPoint,
571  PstreamBuffers& pBufs,
572  labelHashSet& changedPoints
573 )
574 {
575  // Receive all my neighbours' information and merge with mine.
576  // After finishing will have updated
577  // - procPoints_ : all neighbour information merged in.
578  // - meshToProcPoint_
579  // - changedPoints: all points for which something changed.
580 
581  const polyBoundaryMesh& patches = mesh_.boundaryMesh();
582  const labelPairList& patchInfo = globalTransforms_.patchTransformSign();
583 
584  // Reset changed points
585  changedPoints.clear();
586 
587  forAll(patches, patchi)
588  {
589  const polyPatch& pp = patches[patchi];
590 
591  if
592  (
593  (Pstream::parRun() && isA<processorPolyPatch>(pp))
594  && (mergeSeparated || patchInfo[patchi].first() == -1)
595  )
596  {
597  const processorPolyPatch& procPatch =
598  refCast<const processorPolyPatch>(pp);
599 
600  labelList patchFaces;
601  labelList indexInFace;
602  List<labelPairList> nbrInfo;
603 
604  {
605  UIPstream fromNeighbour(procPatch.neighbProcNo(), pBufs);
606  fromNeighbour >> patchFaces >> indexInFace >> nbrInfo;
607  }
608 
609  if (debug)
610  {
611  Pout<< " On " << pp.name()
612  << " Received from "
613  << procPatch.neighbProcNo() << " point information:"
614  << patchFaces.size() << endl;
615  }
616 
617  forAll(patchFaces, i)
618  {
619  const face& f = pp[patchFaces[i]];
620 
621  // Get index in this face from index on face on other side.
622  label index = (f.size() - indexInFace[i]) % f.size();
623 
624  // Get the meshpoint on my side
625  label meshPointi = f[index];
626 
627  label localPointi = meshToLocalPoint
628  (
629  meshToPatchPoint,
630  meshPointi
631  );
632 
633  if (mergeInfo(nbrInfo[i], localPointi))
634  {
635  changedPoints.insert(localPointi);
636  }
637  }
638  }
639  else if
640  (
641  (
642  isA<cyclicPolyPatch>(pp)
643  && refCast<const cyclicPolyPatch>(pp).owner()
644  )
645  && (mergeSeparated || patchInfo[patchi].first() == -1)
646  )
647  {
648  // Handle cyclics: send lower half to upper half and vice versa.
649  // Or since they both are in memory just do it point by point.
650 
651  const cyclicPolyPatch& cycPatch =
652  refCast<const cyclicPolyPatch>(pp);
653 
654  // Pout<< "Patch:" << patchi << " name:" << pp.name() << endl;
655 
656  const labelList& meshPoints = pp.meshPoints();
657  const labelList coupledMeshPoints(reverseMeshPoints(cycPatch));
658 
659  forAll(meshPoints, i)
660  {
661  label meshPointA = meshPoints[i];
662  label meshPointB = coupledMeshPoints[i];
663 
664  if (meshPointA != meshPointB)
665  {
666  // Pout<< "Connection between point " << meshPointA
667  // << " at " << mesh_.points()[meshPointA]
668  // << " and " << meshPointB
669  // << " at " << mesh_.points()[meshPointB] << endl;
670 
671  label localA = meshToLocalPoint
672  (
673  meshToPatchPoint,
674  meshPointA
675  );
676  label localB = meshToLocalPoint
677  (
678  meshToPatchPoint,
679  meshPointB
680  );
681 
682 
683  // Do we have information on pointA?
684  Map<label>::iterator procPointA =
685  meshToProcPoint_.find(localA);
686 
687  if (procPointA != meshToProcPoint_.end())
688  {
689  const labelPairList infoA = addSendTransform
690  (
691  cycPatch.index(),
692  procPoints_[procPointA()]
693  );
694 
695  if (mergeInfo(infoA, localB))
696  {
697  changedPoints.insert(localB);
698  }
699  }
700 
701  // Same for info on pointB
702  Map<label>::iterator procPointB =
703  meshToProcPoint_.find(localB);
704 
705  if (procPointB != meshToProcPoint_.end())
706  {
707  const labelPairList infoB = addSendTransform
708  (
709  cycPatch.nbrPatchID(),
710  procPoints_[procPointB()]
711  );
712 
713  if (mergeInfo(infoB, localA))
714  {
715  changedPoints.insert(localA);
716  }
717  }
718  }
719  }
720  }
721  }
722 }
723 
724 
725 void Foam::globalPoints::remove
726 (
727  const labelList& patchToMeshPoint,
728  const Map<label>& directNeighbours
729 )
730 {
731  // Remove entries which are handled by normal face-face communication. I.e.
732  // those points where the equivalence list is only me and my (face)neighbour
733 
734  // Save old ones.
735  Map<label> oldMeshToProcPoint(move(meshToProcPoint_));
736  meshToProcPoint_.resize(oldMeshToProcPoint.size());
737  DynamicList<labelPairList> oldProcPoints(move(procPoints_));
738  procPoints_.setCapacity(oldProcPoints.size());
739 
740  // Go through all equivalences
741  forAllConstIter(Map<label>, oldMeshToProcPoint, iter)
742  {
743  label localPointi = iter.key();
744  const labelPairList& pointInfo = oldProcPoints[iter()];
745 
746  if (pointInfo.size() == 2)
747  {
748  // I will be in this equivalence list.
749  // Check whether my direct (=face) neighbour
750  // is in it. This would be an ordinary connection and can be
751  // handled by normal face-face connectivity.
752 
753  label proc0 = globalTransforms_.processor(pointInfo[0]);
754  label proc1 = globalTransforms_.processor(pointInfo[1]);
755 
756  if
757  (
758  (
759  proc0 == Pstream::myProcNo()
760  && directNeighbours.found
761  (
762  globalTransforms_.index(pointInfo[0])
763  )
764  )
765  || (
766  proc1 == Pstream::myProcNo()
767  && directNeighbours.found
768  (
769  globalTransforms_.index(pointInfo[1])
770  )
771  )
772  )
773  {
774  // Normal faceNeighbours
775  if (proc0 == Pstream::myProcNo())
776  {
777  // Pout<< "Removing direct neighbour:"
778  // << mesh_.points()
779  // [globalTransforms_.index(pointInfo[0])]
780  // << endl;
781  }
782  else if (proc1 == Pstream::myProcNo())
783  {
784  // Pout<< "Removing direct neighbour:"
785  // << mesh_.points()
786  // [globalTransforms_.index(pointInfo[1])]
787  // << endl;
788  }
789  }
790  else
791  {
792  // This condition will be very rare: points are used by
793  // two processors which are not face-face connected.
794  // e.g.
795  // +------+------+
796  // | wall | B |
797  // +------+------+
798  // | A | wall |
799  // +------+------+
800  // Processor A and B share a point. Note that this only will
801  // be found if the two domains are face connected at all
802  // (not shown in the picture)
803 
804  meshToProcPoint_.insert(localPointi, procPoints_.size());
805  procPoints_.append(pointInfo);
806  }
807  }
808  else if (pointInfo.size() == 1)
809  {
810  // This happens for 'wedge' like cyclics where the two halves
811  // come together in the same point so share the same meshPoint.
812  // So this meshPoint will have info of size one only.
813  if
814  (
815  globalTransforms_.processor(pointInfo[0])
816  != Pstream::myProcNo()
817  || !directNeighbours.found
818  (
819  globalTransforms_.index(pointInfo[0])
820  )
821  )
822  {
823  meshToProcPoint_.insert(localPointi, procPoints_.size());
824  procPoints_.append(pointInfo);
825  }
826  }
827  else
828  {
829  meshToProcPoint_.insert(localPointi, procPoints_.size());
830  procPoints_.append(pointInfo);
831  }
832  }
833 
834  procPoints_.shrink();
835  meshToProcPoint_.resize(2*procPoints_.size());
836 }
837 
838 
839 Foam::labelList Foam::globalPoints::reverseMeshPoints
840 (
841  const cyclicPolyPatch& pp
842 )
843 {
844  const cyclicPolyPatch& nbrPatch = pp.nbrPatch();
845 
846  faceList masterFaces(nbrPatch.size());
847 
848  forAll(nbrPatch, facei)
849  {
850  masterFaces[facei] = nbrPatch[facei].reverseFace();
851  }
852 
853  return primitiveFacePatch
854  (
855  masterFaces,
856  nbrPatch.points()
857  ).meshPoints();
858 }
859 
860 
861 void Foam::globalPoints::calculateSharedPoints
862 (
863  const Map<label>& meshToPatchPoint, // from mesh point to local numbering
864  const labelList& patchToMeshPoint, // from local numbering to mesh point
865  const bool keepAllPoints,
866  const bool mergeSeparated
867 )
868 {
869  if (debug)
870  {
871  Pout<< "globalPoints::calculateSharedPoints(..) : "
872  << "doing processor to processor communication to get sharedPoints"
873  << endl
874  << " keepAllPoints :" << keepAllPoints << endl
875  << " mergeSeparated:" << mergeSeparated << endl
876  << endl;
877  }
878 
879 
880  labelHashSet changedPoints(2*nPatchPoints_);
881 
882  // Initialise procPoints with my patch points. Keep track of points
883  // inserted (in changedPoints)
884  // There are two possible forms of this:
885  // - initialise with all patch points (allPoints = true). This causes all
886  // patch points to be exchanged so a lot of information gets stored and
887  // transferred. This all gets filtered out later when removing the
888  // equivalence lists of size 2.
889  // - initialise with boundary points of patches only (allPoints = false).
890  // This should work for all decompositions except extreme ones where a
891  // shared point is not on the boundary of any processor patches using it.
892  // This would happen if a domain was pinched such that two patches share
893  // a point or edge.
894  initOwnPoints(meshToPatchPoint, true, changedPoints);
895 
896  // Do one exchange iteration to get neighbour points.
897  {
898  // Note: to use 'scheduled' would have to intersperse send and receive.
899  // So for now just use nonBlocking. Also globalPoints itself gets
900  // constructed by mesh.globalData().patchSchedule() so creates a loop.
901  PstreamBuffers pBufs
902  (
903  (
907  )
908  );
909  sendPatchPoints
910  (
911  mergeSeparated,
912  meshToPatchPoint,
913  pBufs,
914  changedPoints
915  );
916  pBufs.finishedSends();
917  receivePatchPoints
918  (
919  mergeSeparated,
920  meshToPatchPoint,
921  patchToMeshPoint,
922  pBufs,
923  changedPoints
924  );
925  }
926 
927  // Save neighbours reachable through face-face communication.
928  Map<label> neighbourList;
929  if (!keepAllPoints)
930  {
931  neighbourList = meshToProcPoint_;
932  }
933 
934  // Exchange until nothing changes on all processors.
935  bool changed = false;
936 
937  do
938  {
939  PstreamBuffers pBufs
940  (
941  (
945  )
946  );
947  sendPatchPoints
948  (
949  mergeSeparated,
950  meshToPatchPoint,
951  pBufs,
952  changedPoints
953  );
954  pBufs.finishedSends();
955  receivePatchPoints
956  (
957  mergeSeparated,
958  meshToPatchPoint,
959  patchToMeshPoint,
960  pBufs,
961  changedPoints
962  );
963 
964  changed = changedPoints.size() > 0;
965  reduce(changed, orOp<bool>());
966 
967  } while (changed);
968 
969 
970  // Pout<< "**ALL** connected points:" << endl;
971  // forAllConstIter(Map<label>, meshToProcPoint_, iter)
972  //{
973  // label localI = iter.key();
974  // const labelPairList& pointInfo = procPoints_[iter()];
975  // Pout<< "pointi:" << localI << " index:" << iter()
976  // << " coord:"
977  // << mesh_.points()[localToMeshPoint(patchToMeshPoint, localI)]
978  // << endl;
979  // printProcPoints(patchToMeshPoint, pointInfo);
980  // Pout<< endl;
981  //}
982 
983 
984  // Remove direct neighbours from point equivalences.
985  if (!keepAllPoints)
986  {
987  remove(patchToMeshPoint, neighbourList);
988  }
989 
990 
991  // Sort procPoints in incremental order. This will make
992  // the master the first element on all processors.
993  // Note: why not sort in decreasing order? Give more work to higher
994  // processors.
995  forAllConstIter(Map<label>, meshToProcPoint_, iter)
996  {
997  labelPairList& pointInfo = procPoints_[iter()];
998  sort(pointInfo, globalIndexAndTransform::less(globalTransforms_));
999  }
1000 
1001 
1002  // We now have - in procPoints_ - a list of points which are shared between
1003  // multiple processors. Filter into non-transformed and transformed
1004  // connections.
1005 
1006  pointPoints_.setSize(globalIndices_.localSize());
1007  List<labelPairList> transformedPoints(globalIndices_.localSize());
1008  forAllConstIter(Map<label>, meshToProcPoint_, iter)
1009  {
1010  const labelPairList& pointInfo = procPoints_[iter()];
1011 
1012  if (pointInfo.size() >= 2)
1013  {
1014  // Since sorted master point is the first element
1015  const labelPair& masterInfo = pointInfo[0];
1016 
1017  if
1018  (
1019  (
1020  globalTransforms_.processor(masterInfo)
1021  == Pstream::myProcNo()
1022  )
1023  && (globalTransforms_.index(masterInfo) == iter.key())
1024  )
1025  {
1026  labelList& pPoints = pointPoints_[iter.key()];
1027  pPoints.setSize(pointInfo.size()-1);
1028 
1029  labelPairList& trafoPPoints = transformedPoints[iter.key()];
1030  trafoPPoints.setSize(pointInfo.size()-1);
1031 
1032  label nonTransformI = 0;
1033  label transformI = 0;
1034 
1035  for (label i = 1; i < pointInfo.size(); i++)
1036  {
1037  const labelPair& info = pointInfo[i];
1038  label proci = globalTransforms_.processor(info);
1039  label index = globalTransforms_.index(info);
1040  label transform = globalTransforms_.transformIndex
1041  (
1042  info
1043  );
1044 
1045  if (transform == globalTransforms_.nullTransformIndex())
1046  {
1047  pPoints[nonTransformI++] = globalIndices_.toGlobal
1048  (
1049  proci,
1050  index
1051  );
1052  }
1053  else
1054  {
1055  trafoPPoints[transformI++] = info;
1056  }
1057  }
1058 
1059  pPoints.setSize(nonTransformI);
1060  trafoPPoints.setSize(transformI);
1061  }
1062  }
1063  }
1064 
1065 
1066  List<Map<label>> compactMap;
1067  map_.reset
1068  (
1069  new mapDistribute
1070  (
1071  globalIndices_,
1072  pointPoints_,
1073 
1074  globalTransforms_,
1075  transformedPoints,
1076  transformedPointPoints_,
1077 
1078  compactMap
1079  )
1080  );
1081 
1082  if (debug)
1083  {
1084  Pout<< "globalPoints::calculateSharedPoints(..) : "
1085  << "Finished global points" << endl;
1086  }
1087 }
1088 
1089 
1090 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
1091 
1094  const polyMesh& mesh,
1095  const bool keepAllPoints,
1096  const bool mergeSeparated
1097 )
1098 :
1099  mesh_(mesh),
1100  globalIndices_(mesh_.nPoints()),
1101  globalTransforms_(mesh),
1102  nPatchPoints_(countPatchPoints(mesh.boundaryMesh())),
1103  procPoints_(nPatchPoints_),
1104  meshToProcPoint_(nPatchPoints_)
1105 {
1106  // Empty patch maps to signal storing mesh point labels
1107  Map<label> meshToPatchPoint(0);
1108  labelList patchToMeshPoint(0);
1109 
1110  calculateSharedPoints
1111  (
1112  meshToPatchPoint,
1113  patchToMeshPoint,
1114  keepAllPoints,
1115  mergeSeparated
1116  );
1117 }
1118 
1119 
1122  const polyMesh& mesh,
1123  const indirectPrimitivePatch& coupledPatch,
1124  const bool keepAllPoints,
1125  const bool mergeSeparated
1126 )
1127 :
1128  mesh_(mesh),
1129  globalIndices_(coupledPatch.nPoints()),
1130  globalTransforms_(mesh),
1131  nPatchPoints_(coupledPatch.nPoints()),
1132  procPoints_(nPatchPoints_),
1133  meshToProcPoint_(nPatchPoints_)
1134 {
1135  calculateSharedPoints
1136  (
1137  coupledPatch.meshPointMap(),
1138  coupledPatch.meshPoints(),
1139  keepAllPoints,
1140  mergeSeparated
1141  );
1142 }
1143 
1144 
1145 // ************************************************************************* //
const polyBoundaryMesh & boundaryMesh() const
Return boundary mesh.
Definition: polyMesh.H:434
virtual const fileName & name() const
Return the name of the stream.
Definition: OSstream.H:82
label nPoints() const
Return number of points supporting patch faces.
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: HashTable.H:59
HashTable< label, label, Hash< label > >::iterator iterator
Definition: Map.H:56
static int myProcNo(const label communicator=0)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:429
List< face > faceList
Definition: faceListFwd.H:43
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
static bool less(const vector &x, const vector &y)
To compare normals.
const labelList & meshPoints() const
Return labelList of mesh points in patch. They are constructed.
HashSet< label, Hash< label > > labelHashSet
A HashSet with label keys.
Definition: HashSet.H:211
A list of faces which address into the list of points.
const Map< label > & meshPointMap() const
Mesh point map. Given the global point index find its.
void sort(UList< T > &)
Definition: UList.C:115
Pair< label > labelPair
Label pair.
Definition: labelPair.H:48
List< label > labelList
A List of labels.
Definition: labelList.H:56
List< labelPair > labelPairList
List of labelPairs.
Definition: labelPair.H:49
forAllConstIter(PtrDictionary< phaseModel >, mixture.phases(), phase)
Definition: pEqn.H:29
defineTypeNameAndDebug(combustionModel, 0)
label findIndex(const ListType &, typename ListType::const_reference, const label start=0)
Find first occurrence of given element and return index,.
PrimitivePatch< List< face >, const pointField & > primitiveFacePatch
Foam::primitiveFacePatch.
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
static commsTypes defaultCommsType
Default commsType.
Definition: UPstream.H:272
void setSize(const label)
Reset size of List.
Definition: List.C:281
static bool & parRun()
Is this a parallel run?
Definition: UPstream.H:399
label patchi
prefixOSstream Pout(cout, "Pout")
Definition: IOstreams.H:53
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:74
globalPoints(const polyMesh &mesh, const bool keepAllPoints, const bool mergeSeparated)
Construct from mesh.
Namespace for OpenFOAM.