globalPoints.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | Copyright (C) 2011-2013 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 // Total number of points on coupled patches. Is upper limit for number
43 // of shared points
45 (
47 )
48 {
49  label nTotPoints = 0;
50 
51  forAll(patches, patchI)
52  {
53  const polyPatch& pp = patches[patchI];
54  if (pp.coupled())
55  {
56  nTotPoints += pp.nPoints();
57  }
58  }
59  return nTotPoints;
60 }
61 
62 
64 (
65  const labelPairList& allInfo,
66  const labelPair& info
67 ) const
68 {
69  const label procI = globalIndexAndTransform::processor(info);
70  const label index = globalIndexAndTransform::index(info);
71 
72  forAll(allInfo, i)
73  {
74  if
75  (
76  globalIndexAndTransform::processor(allInfo[i]) == procI
77  && globalIndexAndTransform::index(allInfo[i]) == index
78  )
79  {
80  return i;
81  }
82  }
83  return -1;
84 }
85 
86 
88 (
89  const label patchI,
90  const labelPairList& info
91 ) const
92 {
93  scalar tol = refCast<const coupledPolyPatch>
94  (
95  mesh_.boundaryMesh()[patchI]
96  ).matchTolerance();
97 
98  labelPairList sendInfo(info.size());
99 
100  forAll(info, i)
101  {
102  //Pout<< " adding send transform to" << nl
103  // << " proc:" << globalIndexAndTransform::processor(info[i])
104  // << nl
105  // << " index:" << globalIndexAndTransform::index(info[i]) << nl
106  // << " trafo:"
107  // << globalTransforms_.decodeTransformIndex
108  // (globalIndexAndTransform::transformIndex(info[i]))
109  // << endl;
110 
111  sendInfo[i] = globalIndexAndTransform::encode
112  (
113  globalIndexAndTransform::processor(info[i]),
114  globalIndexAndTransform::index(info[i]),
115  globalTransforms_.addToTransformIndex
116  (
117  globalIndexAndTransform::transformIndex(info[i]),
118  patchI,
119  true, // patchI is sending side
120  tol // tolerance for comparison
121  )
122  );
123  }
124  return sendInfo;
125 }
126 
127 
128 // Collect all topological information about a point on a patch.
129 // (this information is the patch faces using the point and the relative
130 // position of the point in the face)
132 (
133  const polyPatch& pp,
134  const label patchPointI,
135  const labelPairList& knownInfo,
136 
138  DynamicList<label>& indexInFace,
140 ) const
141 {
142  label meshPointI = pp.meshPoints()[patchPointI];
143 
144  // Add all faces using the point so we are sure we find it on the
145  // other side.
146  const labelList& pFaces = pp.pointFaces()[patchPointI];
147 
148  forAll(pFaces, i)
149  {
150  label patchFaceI = pFaces[i];
151 
152  const face& f = pp[patchFaceI];
153 
154  patchFaces.append(patchFaceI);
155  indexInFace.append(findIndex(f, meshPointI));
156 
157  // Add patch transformation
158  allInfo.append(addSendTransform(pp.index(), knownInfo));
159  }
160 }
161 
162 
163 // Add nbrInfo to myInfo. Return true if anything changed.
164 // nbrInfo is for a point a list of all the global points using it
166 (
167  const labelPairList& nbrInfo,
168  const label localPointI,
169  labelPairList& myInfo
170 ) const
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 = globalIndexAndTransform::transformIndex
208  (
209  myInfo[index]
210  );
211  label nbrTransform = globalIndexAndTransform::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 
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 
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 // Updates database of current information on meshpoints with nbrInfo.
271 // Uses mergeInfo above. Returns true if data kept for meshPointI changed.
273 (
274  const labelPairList& nbrInfo,
275  const label localPointI
276 )
277 {
278  label infoChanged = false;
279 
280  // Get the index into the procPoints list.
281  Map<label>::iterator iter = meshToProcPoint_.find(localPointI);
282 
283  if (iter != meshToProcPoint_.end())
284  {
285  if (mergeInfo(nbrInfo, localPointI, procPoints_[iter()]))
286  {
287  infoChanged = true;
288  }
289  }
290  else
291  {
292  // Construct local index for point
293  labelPairList knownInfo
294  (
295  1,
296  globalIndexAndTransform::encode
297  (
298  Pstream::myProcNo(),
299  localPointI,
300  globalTransforms_.nullTransformIndex()
301  )
302  );
303 
304  if (mergeInfo(nbrInfo, localPointI, knownInfo))
305  {
306  // Update addressing from into procPoints
307  meshToProcPoint_.insert(localPointI, procPoints_.size());
308  // Insert into list of equivalences.
309  procPoints_.append(knownInfo);
310 
311  infoChanged = true;
312  }
313  }
314  return infoChanged;
315 }
316 
317 
318 // Updates database of current information on meshpoints with nbrInfo.
319 // Uses mergeInfo above. Returns true if data kept for meshPointI changed.
321 (
322  const labelPairList& nbrInfo,
323  const label localPointI
324 )
325 {
326  label infoChanged = false;
327 
328  // Get the index into the procPoints list.
329  Map<label>::iterator iter = meshToProcPoint_.find(localPointI);
330 
331  if (iter != meshToProcPoint_.end())
332  {
333  if (mergeInfo(nbrInfo, localPointI, procPoints_[iter()]))
334  {
335  infoChanged = true;
336  }
337  }
338  else
339  {
340  // Update addressing into procPoints
341  meshToProcPoint_.insert(localPointI, procPoints_.size());
342  // Insert into list of equivalences.
343  procPoints_.append(nbrInfo);
344 
345  infoChanged = true;
346  }
347  return infoChanged;
348 }
349 
350 
352 (
353  const labelList& patchToMeshPoint,
354  const labelPair& pointInfo
355 ) const
356 {
357  label procI = globalIndexAndTransform::processor(pointInfo);
358  label index = globalIndexAndTransform::index(pointInfo);
359  label trafoI = globalIndexAndTransform::transformIndex(pointInfo);
360 
361  Pout<< " proc:" << procI;
362  Pout<< " localpoint:";
363  Pout<< index;
364  Pout<< " through transform:"
365  << trafoI << " bits:"
366  << globalTransforms_.decodeTransformIndex(trafoI);
367 
368  if (procI == Pstream::myProcNo())
369  {
370  label meshPointI = localToMeshPoint(patchToMeshPoint, index);
371  Pout<< " at:" << mesh_.points()[meshPointI];
372  }
373 }
374 
375 
377 (
378  const labelList& patchToMeshPoint,
379  const labelPairList& pointInfo
380 ) const
381 {
382  forAll(pointInfo, i)
383  {
384  printProcPoint(patchToMeshPoint, pointInfo[i]);
385  Pout<< endl;
386  }
387 }
388 
389 
390 // Insert my own points into structure and mark as changed.
392 (
393  const Map<label>& meshToPatchPoint,
394  const bool allPoints,
395  labelHashSet& changedPoints
396 )
397 {
398  const polyBoundaryMesh& patches = mesh_.boundaryMesh();
399 
400  forAll(patches, patchI)
401  {
402  const polyPatch& pp = patches[patchI];
403 
404  if (pp.coupled())
405  {
406  const labelList& meshPoints = pp.meshPoints();
407 
408  if (allPoints)
409  {
410  // All points on patch
411  forAll(meshPoints, patchPointI)
412  {
413  label meshPointI = meshPoints[patchPointI];
414  label localPointI = meshToLocalPoint
415  (
416  meshToPatchPoint,
417  meshPointI
418  );
419 
420  labelPairList knownInfo
421  (
422  1,
423  globalIndexAndTransform::encode
424  (
425  Pstream::myProcNo(),
426  localPointI,
427  globalTransforms_.nullTransformIndex()
428  )
429  );
430 
431  //Pout<< "For point "<< pp.points()[meshPointI]
432  // << " inserting info " << knownInfo
433  // << endl;
434 
435  // Update changedpoints info.
436  if (storeInitialInfo(knownInfo, localPointI))
437  {
438  changedPoints.insert(localPointI);
439  }
440  }
441  }
442  else
443  {
444  // Boundary points only
445  const labelList& boundaryPoints = pp.boundaryPoints();
446 
447  forAll(boundaryPoints, i)
448  {
449  label meshPointI = meshPoints[boundaryPoints[i]];
450  label localPointI = meshToLocalPoint
451  (
452  meshToPatchPoint,
453  meshPointI
454  );
455 
456  labelPairList knownInfo
457  (
458  1,
459  globalIndexAndTransform::encode
460  (
461  Pstream::myProcNo(),
462  localPointI,
463  globalTransforms_.nullTransformIndex()
464  )
465  );
466 
467  if (storeInitialInfo(knownInfo, localPointI))
468  {
469  changedPoints.insert(localPointI);
470  }
471  }
472  }
473  }
474  }
475 }
476 
477 
478 // Send all my info on changedPoints_ to my neighbours.
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
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 // Receive all my neighbours' information and merge with mine.
567 // After finishing will have updated
568 // - procPoints_ : all neighbour information merged in.
569 // - meshToProcPoint_
570 // - changedPoints: all points for which something changed.
572 (
573  const bool mergeSeparated,
574  const Map<label>& meshToPatchPoint,
575  const labelList& patchToMeshPoint,
576  PstreamBuffers& pBufs,
577  labelHashSet& changedPoints
578 )
579 {
580  const polyBoundaryMesh& patches = mesh_.boundaryMesh();
581  const labelPairList& patchInfo = globalTransforms_.patchTransformSign();
582 
583  // Reset changed points
584  changedPoints.clear();
585 
586  forAll(patches, patchI)
587  {
588  const polyPatch& pp = patches[patchI];
589 
590  if
591  (
592  (Pstream::parRun() && isA<processorPolyPatch>(pp))
593  && (mergeSeparated || patchInfo[patchI].first() == -1)
594  )
595  {
596  const processorPolyPatch& procPatch =
597  refCast<const processorPolyPatch>(pp);
598 
600  labelList indexInFace;
601  List<labelPairList> nbrInfo;
602 
603  {
604  UIPstream fromNeighbour(procPatch.neighbProcNo(), pBufs);
605  fromNeighbour >> patchFaces >> indexInFace >> nbrInfo;
606  }
607 
608  if (debug)
609  {
610  Pout<< " On " << pp.name()
611  << " Received from "
612  << procPatch.neighbProcNo() << " point information:"
613  << patchFaces.size() << endl;
614  }
615 
616  forAll(patchFaces, i)
617  {
618  const face& f = pp[patchFaces[i]];
619 
620  // Get index in this face from index on face on other side.
621  label index = (f.size() - indexInFace[i]) % f.size();
622 
623  // Get the meshpoint on my side
624  label meshPointI = f[index];
625 
626  label localPointI = meshToLocalPoint
627  (
628  meshToPatchPoint,
629  meshPointI
630  );
631 
632  if (mergeInfo(nbrInfo[i], localPointI))
633  {
634  changedPoints.insert(localPointI);
635  }
636  }
637  }
638  else if
639  (
640  (
641  isA<cyclicPolyPatch>(pp)
642  && refCast<const cyclicPolyPatch>(pp).owner()
643  )
644  && (mergeSeparated || patchInfo[patchI].first() == -1)
645  )
646  {
647  // Handle cyclics: send lower half to upper half and vice versa.
648  // Or since they both are in memory just do it point by point.
649 
650  const cyclicPolyPatch& cycPatch =
651  refCast<const cyclicPolyPatch>(pp);
652 
653  //Pout<< "Patch:" << patchI << " name:" << pp.name() << endl;
654 
655  const labelList& meshPoints = pp.meshPoints();
656  const labelList coupledMeshPoints(reverseMeshPoints(cycPatch));
657 
658  forAll(meshPoints, i)
659  {
660  label meshPointA = meshPoints[i];
661  label meshPointB = coupledMeshPoints[i];
662 
663  if (meshPointA != meshPointB)
664  {
665  //Pout<< "Connection between point " << meshPointA
666  // << " at " << mesh_.points()[meshPointA]
667  // << " and " << meshPointB
668  // << " at " << mesh_.points()[meshPointB] << endl;
669 
670  label localA = meshToLocalPoint
671  (
672  meshToPatchPoint,
673  meshPointA
674  );
675  label localB = meshToLocalPoint
676  (
677  meshToPatchPoint,
678  meshPointB
679  );
680 
681 
682  // Do we have information on pointA?
683  Map<label>::iterator procPointA =
684  meshToProcPoint_.find(localA);
685 
686  if (procPointA != meshToProcPoint_.end())
687  {
688  const labelPairList infoA = addSendTransform
689  (
690  cycPatch.index(),
691  procPoints_[procPointA()]
692  );
693 
694  if (mergeInfo(infoA, localB))
695  {
696  changedPoints.insert(localB);
697  }
698  }
699 
700  // Same for info on pointB
701  Map<label>::iterator procPointB =
702  meshToProcPoint_.find(localB);
703 
704  if (procPointB != meshToProcPoint_.end())
705  {
706  const labelPairList infoB = addSendTransform
707  (
708  cycPatch.neighbPatchID(),
709  procPoints_[procPointB()]
710  );
711 
712  if (mergeInfo(infoB, localA))
713  {
714  changedPoints.insert(localA);
715  }
716  }
717  }
718  }
719  }
720  }
721 }
722 
723 
724 // Remove entries which are handled by normal face-face communication. I.e.
725 // those points where the equivalence list is only me and my (face)neighbour
727 (
728  const labelList& patchToMeshPoint,
729  const Map<label>& directNeighbours
730 )
731 {
732  // Save old ones.
733  Map<label> oldMeshToProcPoint(meshToProcPoint_.xfer());
734  meshToProcPoint_.resize(oldMeshToProcPoint.size());
735  DynamicList<labelPairList> oldProcPoints(procPoints_.xfer());
736  procPoints_.setCapacity(oldProcPoints.size());
737 
738  // Go through all equivalences
739  forAllConstIter(Map<label>, oldMeshToProcPoint, iter)
740  {
741  label localPointI = iter.key();
742  const labelPairList& pointInfo = oldProcPoints[iter()];
743 
744  if (pointInfo.size() == 2)
745  {
746  // I will be in this equivalence list.
747  // Check whether my direct (=face) neighbour
748  // is in it. This would be an ordinary connection and can be
749  // handled by normal face-face connectivity.
750 
751  label proc0 = globalIndexAndTransform::processor(pointInfo[0]);
752  label proc1 = globalIndexAndTransform::processor(pointInfo[1]);
753 
754  if
755  (
756  (
757  proc0 == Pstream::myProcNo()
758  && directNeighbours.found
759  (
760  globalIndexAndTransform::index(pointInfo[0])
761  )
762  )
763  || (
764  proc1 == Pstream::myProcNo()
765  && directNeighbours.found
766  (
767  globalIndexAndTransform::index(pointInfo[1])
768  )
769  )
770  )
771  {
772  // Normal faceNeighbours
773  if (proc0 == Pstream::myProcNo())
774  {
775  //Pout<< "Removing direct neighbour:"
776  // << mesh_.points()
777  // [globalIndexAndTransform::index(pointInfo[0])]
778  // << endl;
779  }
780  else if (proc1 == Pstream::myProcNo())
781  {
782  //Pout<< "Removing direct neighbour:"
783  // << mesh_.points()
784  // [globalIndexAndTransform::index(pointInfo[1])]
785  // << endl;
786  }
787  }
788  else
789  {
790  // This condition will be very rare: points are used by
791  // two processors which are not face-face connected.
792  // e.g.
793  // +------+------+
794  // | wall | B |
795  // +------+------+
796  // | A | wall |
797  // +------+------+
798  // Processor A and B share a point. Note that this only will
799  // be found if the two domains are face connected at all
800  // (not shown in the picture)
801 
802  meshToProcPoint_.insert(localPointI, procPoints_.size());
803  procPoints_.append(pointInfo);
804  }
805  }
806  else if (pointInfo.size() == 1)
807  {
808  // This happens for 'wedge' like cyclics where the two halves
809  // come together in the same point so share the same meshPoint.
810  // So this meshPoint will have info of size one only.
811  if
812  (
813  globalIndexAndTransform::processor(pointInfo[0])
814  != Pstream::myProcNo()
815  || !directNeighbours.found
816  (
817  globalIndexAndTransform::index(pointInfo[0])
818  )
819  )
820  {
821  meshToProcPoint_.insert(localPointI, procPoints_.size());
822  procPoints_.append(pointInfo);
823  }
824  }
825  else
826  {
827  meshToProcPoint_.insert(localPointI, procPoints_.size());
828  procPoints_.append(pointInfo);
829  }
830  }
831 
832  procPoints_.shrink();
833  meshToProcPoint_.resize(2*procPoints_.size());
834 }
835 
836 
838 (
839  const cyclicPolyPatch& pp
840 )
841 {
842  const cyclicPolyPatch& nbrPatch = pp.neighbPatch();
843 
844  faceList masterFaces(nbrPatch.size());
845 
846  forAll(nbrPatch, faceI)
847  {
848  masterFaces[faceI] = nbrPatch[faceI].reverseFace();
849  }
850 
851  return primitiveFacePatch
852  (
853  masterFaces,
854  nbrPatch.points()
855  ).meshPoints();
856 }
857 
858 
860 (
861  const Map<label>& meshToPatchPoint, // from mesh point to local numbering
862  const labelList& patchToMeshPoint, // from local numbering to mesh point
863  const bool keepAllPoints,
864  const bool mergeSeparated
865 )
866 {
867  if (debug)
868  {
869  Pout<< "globalPoints::calculateSharedPoints(..) : "
870  << "doing processor to processor communication to get sharedPoints"
871  << endl
872  << " keepAllPoints :" << keepAllPoints << endl
873  << " mergeSeparated:" << mergeSeparated << endl
874  << endl;
875  }
876 
877 
878  labelHashSet changedPoints(2*nPatchPoints_);
879 
880  // Initialize procPoints with my patch points. Keep track of points
881  // inserted (in changedPoints)
882  // There are two possible forms of this:
883  // - initialize with all patch points (allPoints = true). This causes all
884  // patch points to be exchanged so a lot of information gets stored and
885  // transferred. This all gets filtered out later when removing the
886  // equivalence lists of size 2.
887  // - initialize with boundary points of patches only (allPoints = false).
888  // This should work for all decompositions except extreme ones where a
889  // shared point is not on the boundary of any processor patches using it.
890  // This would happen if a domain was pinched such that two patches share
891  // a point or edge.
892  initOwnPoints(meshToPatchPoint, true, changedPoints);
893 
894  // Do one exchange iteration to get neighbour points.
895  {
896  // Note: to use 'scheduled' would have to intersperse send and receive.
897  // So for now just use nonBlocking. Also globalPoints itself gets
898  // constructed by mesh.globalData().patchSchedule() so creates a loop.
899  PstreamBuffers pBufs
900  (
901  (
902  Pstream::defaultCommsType == Pstream::scheduled
903  ? Pstream::nonBlocking
904  : Pstream::defaultCommsType
905  )
906  );
907  sendPatchPoints
908  (
909  mergeSeparated,
910  meshToPatchPoint,
911  pBufs,
912  changedPoints
913  );
914  pBufs.finishedSends();
915  receivePatchPoints
916  (
917  mergeSeparated,
918  meshToPatchPoint,
919  patchToMeshPoint,
920  pBufs,
921  changedPoints
922  );
923  }
924 
925  // Save neighbours reachable through face-face communication.
926  Map<label> neighbourList;
927  if (!keepAllPoints)
928  {
929  neighbourList = meshToProcPoint_;
930  }
931 
932  // Exchange until nothing changes on all processors.
933  bool changed = false;
934 
935  do
936  {
937  PstreamBuffers pBufs
938  (
939  (
940  Pstream::defaultCommsType == Pstream::scheduled
941  ? Pstream::nonBlocking
942  : Pstream::defaultCommsType
943  )
944  );
945  sendPatchPoints
946  (
947  mergeSeparated,
948  meshToPatchPoint,
949  pBufs,
950  changedPoints
951  );
952  pBufs.finishedSends();
953  receivePatchPoints
954  (
955  mergeSeparated,
956  meshToPatchPoint,
957  patchToMeshPoint,
958  pBufs,
959  changedPoints
960  );
961 
962  changed = changedPoints.size() > 0;
963  reduce(changed, orOp<bool>());
964 
965  } while (changed);
966 
967 
968  //Pout<< "**ALL** connected points:" << endl;
969  //forAllConstIter(Map<label>, meshToProcPoint_, iter)
970  //{
971  // label localI = iter.key();
972  // const labelPairList& pointInfo = procPoints_[iter()];
973  // Pout<< "pointI:" << localI << " index:" << iter()
974  // << " coord:"
975  // << mesh_.points()[localToMeshPoint(patchToMeshPoint, localI)]
976  // << endl;
977  // printProcPoints(patchToMeshPoint, pointInfo);
978  // Pout<< endl;
979  //}
980 
981 
982  // Remove direct neighbours from point equivalences.
983  if (!keepAllPoints)
984  {
985  remove(patchToMeshPoint, neighbourList);
986  }
987 
988 
989  // Sort procPoints in incremental order. This will make
990  // the master the first element on all processors.
991  // Note: why not sort in decreasing order? Give more work to higher
992  // processors.
993  forAllConstIter(Map<label>, meshToProcPoint_, iter)
994  {
995  labelPairList& pointInfo = procPoints_[iter()];
996  sort(pointInfo, globalIndexAndTransform::less());
997  }
998 
999 
1000  // We now have - in procPoints_ - a list of points which are shared between
1001  // multiple processors. Filter into non-transformed and transformed
1002  // connections.
1003 
1004  pointPoints_.setSize(globalIndices_.localSize());
1005  List<labelPairList> transformedPoints(globalIndices_.localSize());
1006  forAllConstIter(Map<label>, meshToProcPoint_, iter)
1007  {
1008  const labelPairList& pointInfo = procPoints_[iter()];
1009 
1010  if (pointInfo.size() >= 2)
1011  {
1012  // Since sorted master point is the first element
1013  const labelPair& masterInfo = pointInfo[0];
1014 
1015  if
1016  (
1017  (
1018  globalIndexAndTransform::processor(masterInfo)
1019  == Pstream::myProcNo()
1020  )
1021  && (globalIndexAndTransform::index(masterInfo) == iter.key())
1022  )
1023  {
1024  labelList& pPoints = pointPoints_[iter.key()];
1025  pPoints.setSize(pointInfo.size()-1);
1026 
1027  labelPairList& trafoPPoints = transformedPoints[iter.key()];
1028  trafoPPoints.setSize(pointInfo.size()-1);
1029 
1030  label nonTransformI = 0;
1031  label transformI = 0;
1032 
1033  for (label i = 1; i < pointInfo.size(); i++)
1034  {
1035  const labelPair& info = pointInfo[i];
1036  label procI = globalIndexAndTransform::processor(info);
1037  label index = globalIndexAndTransform::index(info);
1038  label transform = globalIndexAndTransform::transformIndex
1039  (
1040  info
1041  );
1042 
1043  if (transform == globalTransforms_.nullTransformIndex())
1044  {
1045  pPoints[nonTransformI++] = globalIndices_.toGlobal
1046  (
1047  procI,
1048  index
1049  );
1050  }
1051  else
1052  {
1053  trafoPPoints[transformI++] = info;
1054  }
1055  }
1056 
1057  pPoints.setSize(nonTransformI);
1058  trafoPPoints.setSize(transformI);
1059  }
1060  }
1061  }
1062 
1063 
1064  List<Map<label> > compactMap;
1065  map_.reset
1066  (
1067  new mapDistribute
1068  (
1069  globalIndices_,
1070  pointPoints_,
1071 
1072  globalTransforms_,
1073  transformedPoints,
1074  transformedPointPoints_,
1075 
1076  compactMap
1077  )
1078  );
1079 
1080  if (debug)
1081  {
1082  Pout<< "globalPoints::calculateSharedPoints(..) : "
1083  << "Finished global points" << endl;
1084  }
1085 }
1086 
1087 
1088 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
1089 
1090 // Construct from mesh
1093  const polyMesh& mesh,
1094  const bool keepAllPoints,
1095  const bool mergeSeparated
1096 )
1097 :
1098  mesh_(mesh),
1099  globalIndices_(mesh_.nPoints()),
1100  globalTransforms_(mesh),
1101  nPatchPoints_(countPatchPoints(mesh.boundaryMesh())),
1102  procPoints_(nPatchPoints_),
1103  meshToProcPoint_(nPatchPoints_)
1104 {
1105  // Empty patch maps to signal storing mesh point labels
1106  Map<label> meshToPatchPoint(0);
1107  labelList patchToMeshPoint(0);
1108 
1109  calculateSharedPoints
1110  (
1111  meshToPatchPoint,
1112  patchToMeshPoint,
1113  keepAllPoints,
1114  mergeSeparated
1115  );
1116 }
1117 
1118 
1119 // Construct from mesh and patch of coupled faces
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 // ************************************************************************* //
Foam::globalPoints::globalPoints
globalPoints(const globalPoints &)
Disallow default bitwise copy construct.
Foam::PrimitivePatch::pointFaces
const labelListList & pointFaces() const
Return point-face addressing.
Definition: PrimitivePatchTemplate.C:352
Foam::globalPoints::reverseMeshPoints
static labelList reverseMeshPoints(const cyclicPolyPatch &)
Return mesh points of other side in same order as my meshPoints.
Definition: globalPoints.C:838
Foam::PrimitivePatch::points
const Field< PointType > & points() const
Return reference to global points.
Definition: PrimitivePatchTemplate.H:282
Foam::UOPstream
Output inter-processor communications stream operating on external buffer.
Definition: UOPstream.H:54
Foam::globalPoints::localToMeshPoint
static label localToMeshPoint(const labelList &patchToMeshPoint, const label localPointI)
Opposite of meshToLocalPoint.
Definition: globalPoints.C:256
Foam::polyBoundaryMesh
Foam::polyBoundaryMesh.
Definition: polyBoundaryMesh.H:60
cyclicPolyPatch.H
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:406
Foam::cyclicPolyPatch
Cyclic plane patch.
Definition: cyclicPolyPatch.H:63
Foam::findIndex
label findIndex(const ListType &, typename ListType::const_reference, const label start=0)
Find first occurence of given element and return index,.
Foam::DynamicList< label >
Foam::cyclicPolyPatch::neighbPatch
const cyclicPolyPatch & neighbPatch() const
Definition: cyclicPolyPatch.H:328
Foam::PstreamBuffers
Buffers for inter-processor communications streams (UOPstream, UIPstream).
Definition: PstreamBuffers.H:85
Foam::polyPatch::coupled
virtual bool coupled() const
Return true if this patch is geometrically coupled (i.e. faces and.
Definition: polyPatch.H:322
Foam::List::transfer
void transfer(List< T > &)
Transfer the contents of the argument List into this list.
Foam::Map< label >
Foam::processorPolyPatch::neighbProcNo
int neighbProcNo() const
Return neigbour processor number.
Definition: processorPolyPatch.H:255
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
Foam::globalPoints::addToSend
void addToSend(const polyPatch &, const label patchPointI, const labelPairList &, DynamicList< label > &patchFaces, DynamicList< label > &indexInFace, DynamicList< labelPairList > &allInfo) const
Add information about patchPointI in relative indices to send.
Definition: globalPoints.C:132
polyMesh.H
Foam::HashSet< label, Hash< label > >
patchFaces
labelList patchFaces(const polyBoundaryMesh &patches, const wordList &names)
Definition: extrudeMesh.C:148
Foam::primitiveFacePatch
PrimitivePatch< face, List, const pointField & > primitiveFacePatch
Foam::primitiveFacePatch.
Definition: primitiveFacePatch.H:45
Foam::polyMesh
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:74
Foam::transform
dimensionSet transform(const dimensionSet &)
Definition: dimensionSet.C:465
forAllConstIter
forAllConstIter(PtrDictionary< phaseModel >, mixture.phases(), phase)
Definition: pEqn.H:39
pFaces
Info<< "Finished reading KIVA file"<< endl;cellShapeList cellShapes(nPoints);labelList cellZoning(nPoints, -1);const cellModel &hex=*(cellModeller::lookup("hex"));labelList hexLabels(8);label activeCells=0;labelList pointMap(nPoints);forAll(pointMap, i){ pointMap[i]=i;}for(label i=0;i< nPoints;i++){ if(f[i] > 0.0) { hexLabels[0]=i;hexLabels[1]=i1tab[i];hexLabels[2]=i3tab[i1tab[i]];hexLabels[3]=i3tab[i];hexLabels[4]=i8tab[i];hexLabels[5]=i1tab[i8tab[i]];hexLabels[6]=i3tab[i1tab[i8tab[i]]];hexLabels[7]=i3tab[i8tab[i]];cellShapes[activeCells]=cellShape(hex, hexLabels);edgeList edges=cellShapes[activeCells].edges();forAll(edges, ei) { if(edges[ei].mag(points)< SMALL) { label start=pointMap[edges[ei].start()];while(start !=pointMap[start]) { start=pointMap[start];} label end=pointMap[edges[ei].end()];while(end !=pointMap[end]) { end=pointMap[end];} label minLabel=min(start, end);pointMap[start]=pointMap[end]=minLabel;} } cellZoning[activeCells]=idreg[i];activeCells++;}}cellShapes.setSize(activeCells);cellZoning.setSize(activeCells);forAll(cellShapes, celli){ cellShape &cs=cellShapes[celli];forAll(cs, i) { cs[i]=pointMap[cs[i]];} cs.collapse();}label bcIDs[11]={-1, 0, 2, 4, -1, 5, -1, 6, 7, 8, 9};const label nBCs=12;const word *kivaPatchTypes[nBCs]={ &wallPolyPatch::typeName, &wallPolyPatch::typeName, &wallPolyPatch::typeName, &wallPolyPatch::typeName, &symmetryPolyPatch::typeName, &wedgePolyPatch::typeName, &polyPatch::typeName, &polyPatch::typeName, &polyPatch::typeName, &polyPatch::typeName, &symmetryPolyPatch::typeName, &oldCyclicPolyPatch::typeName};enum patchTypeNames{ PISTON, VALVE, LINER, CYLINDERHEAD, AXIS, WEDGE, INFLOW, OUTFLOW, PRESIN, PRESOUT, SYMMETRYPLANE, CYCLIC};const char *kivaPatchNames[nBCs]={ "piston", "valve", "liner", "cylinderHead", "axis", "wedge", "inflow", "outflow", "presin", "presout", "symmetryPlane", "cyclic"};List< SLList< face > > pFaces[nBCs]
Definition: readKivaGrid.H:235
Foam::reduce
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
Definition: PstreamReduceOps.H:43
Foam::label
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
Foam::globalPoints::addSendTransform
labelPairList addSendTransform(const label patchI, const labelPairList &info) const
Definition: globalPoints.C:88
Foam::orOp
Definition: ops.H:178
Foam::polyPatch
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:66
Foam::globalPoints::storeInitialInfo
bool storeInitialInfo(const labelPairList &nbrInfo, const label localPointI)
Store (and merge) info for meshPointI.
Definition: globalPoints.C:321
Foam::mapDistribute
Class containing processor-to-processor mapping information.
Definition: mapDistribute.H:152
Foam::processorPolyPatch
Neighbour processor patch.
Definition: processorPolyPatch.H:55
Foam::PstreamBuffers::finishedSends
void finishedSends(const bool block=true)
Mark all sends as having been done. This will start receives.
Definition: PstreamBuffers.C:82
Foam::globalPoints::printProcPoints
void printProcPoints(const labelList &patchToMeshPoint, const labelPairList &pointInfo) const
Definition: globalPoints.C:377
Foam::PrimitivePatch::nPoints
label nPoints() const
Return number of points supporting patch faces.
Definition: PrimitivePatchTemplate.H:293
Foam::globalPoints::mergeInfo
bool mergeInfo(const labelPairList &nbrInfo, const label localPointI, labelPairList &myInfo) const
Merge info from neighbour into my data.
Definition: globalPoints.C:166
processorPolyPatch.H
Foam::HashTable::size
label size() const
Return number of elements in table.
Definition: HashTableI.H:65
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:18
Foam::HashTable::found
bool found(const Key &) const
Return true if hashedEntry is found in table.
Definition: HashTable.C:109
Foam::globalPoints::meshToLocalPoint
static label meshToLocalPoint(const Map< label > &meshToPatchPoint, const label meshPointI)
From mesh point to 'local point'. Is the mesh point itself.
Definition: globalPoints.C:241
Foam
Namespace for OpenFOAM.
Definition: combustionModel.C:30
Foam::globalPoints::calculateSharedPoints
void calculateSharedPoints(const Map< label > &, const labelList &, const bool keepAllPoints, const bool mergeSeparated)
Do all calculations.
Definition: globalPoints.C:860
Foam::DynamicList::append
DynamicList< T, SizeInc, SizeMult, SizeDiv > & append(const T &)
Append an element at the end of the list.
Foam::PrimitivePatch::boundaryPoints
const labelList & boundaryPoints() const
Return list of boundary points,.
Definition: PrimitivePatchTemplate.C:252
Foam::List::setSize
void setSize(const label)
Reset size of List.
Foam::globalPoints::receivePatchPoints
void receivePatchPoints(const bool mergeSeparated, const Map< label > &, const labelList &, PstreamBuffers &, labelHashSet &)
Receive neighbour points and merge into my procPoints.
Definition: globalPoints.C:572
Foam::Pair
An ordered pair of two objects of type <T> with first() and second() elements.
Definition: contiguous.H:49
Foam::Pout
prefixOSstream Pout(cout, "Pout")
Definition: IOstreams.H:53
Foam::HashTable::clear
void clear()
Clear all entries from table.
Definition: HashTable.C:473
mapDistribute.H
f
labelList f(nPoints)
Foam::globalPoints::countPatchPoints
static label countPatchPoints(const polyBoundaryMesh &)
Count all points on processorPatches. Is all points for which.
Definition: globalPoints.C:45
Foam::List
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
Foam::globalIndexAndTransform::less
Less function class used in sorting encoded transforms and indices.
Definition: globalIndexAndTransform.H:71
Foam::globalPoints::printProcPoint
void printProcPoint(const labelList &patchToMeshPoint, const labelPair &pointInfo) const
Debug printing.
Definition: globalPoints.C:352
Foam::HashSet::insert
bool insert(const Key &key)
Insert a new entry.
Definition: HashSet.H:116
Foam::globalPoints::remove
void remove(const labelList &patchToMeshPoint, const Map< label > &)
Remove entries of size 2 where meshPoint is in provided Map.
Definition: globalPoints.C:727
patches
patches[0]
Definition: createSingleCellMesh.H:36
Foam::face
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:75
Foam::DelaunayMeshTools::allPoints
tmp< pointField > allPoints(const Triangulation &t)
Extract all points in vertex-index order.
Foam::sort
void sort(UList< T > &)
Definition: UList.C:107
Foam::List::size
void size(const label)
Override size to be inconsistent with allocated storage.
Foam::UIPstream
Input inter-processor communications stream operating on external buffer.
Definition: UIPstream.H:53
Foam::PrimitivePatch::meshPointMap
const Map< label > & meshPointMap() const
Mesh point map. Given the global point index find its.
Definition: PrimitivePatchTemplate.C:412
Foam::PrimitivePatch::meshPoints
const labelList & meshPoints() const
Return labelList of mesh points in patch.
Definition: PrimitivePatchTemplate.C:392
Foam::defineTypeNameAndDebug
defineTypeNameAndDebug(combustionModel, 0)
Foam::patchIdentifier::name
const word & name() const
Return name.
Definition: patchIdentifier.H:109
Foam::cyclicPolyPatch::neighbPatchID
virtual label neighbPatchID() const
Neighbour patchID.
Definition: cyclicPolyPatch.C:819
Foam::patchIdentifier::index
label index() const
Return the index of this patch in the boundaryMesh.
Definition: patchIdentifier.H:133
Foam::globalPoints::sendPatchPoints
void sendPatchPoints(const bool mergeSeparated, const Map< label > &, PstreamBuffers &, const labelHashSet &) const
Send subset of procPoints to neighbours.
Definition: globalPoints.C:480
Foam::globalPoints::initOwnPoints
void initOwnPoints(const Map< label > &meshToPatchPoint, const bool allPoints, labelHashSet &changedPoints)
Initialize procPoints_ to my patch points. allPoints = true:
Definition: globalPoints.C:392
Foam::PrimitivePatch
A list of faces which address into the list of points.
Definition: PrimitivePatchTemplate.H:88
globalPoints.H
Foam::globalPoints::findSamePoint
label findSamePoint(const labelPairList &allInfo, const labelPair &info) const
Find index of same processor+index.
Definition: globalPoints.C:64