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 | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011-2017 OpenFOAM Foundation
9  Copyright (C) 2019-2022 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "globalPoints.H"
30 #include "processorPolyPatch.H"
31 #include "cyclicPolyPatch.H"
32 #include "polyMesh.H"
33 #include "mapDistribute.H"
34 
35 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
36 
37 namespace Foam
38 {
39  defineTypeNameAndDebug(globalPoints, 0);
40 }
41 
42 
43 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
44 
45 Foam::label Foam::globalPoints::countPatchPoints
46 (
47  const polyBoundaryMesh& patches
48 )
49 {
50  label nTotPoints = 0;
51 
52  for (const polyPatch& pp : patches)
53  {
54  if (pp.coupled())
55  {
56  nTotPoints += pp.nPoints();
57  }
58  }
59  return nTotPoints;
60 }
61 
62 
63 Foam::label Foam::globalPoints::findSamePoint
64 (
65  const labelPairList& allInfo,
66  const labelPair& info
67 ) const
68 {
69  const label proci = globalTransforms_.processor(info);
70  const label index = globalTransforms_.index(info);
71 
72  forAll(allInfo, i)
73  {
74  if
75  (
76  globalTransforms_.processor(allInfo[i]) == proci
77  && globalTransforms_.index(allInfo[i]) == index
78  )
79  {
80  return i;
81  }
82  }
83  return -1;
84 }
85 
86 
87 Foam::labelPairList Foam::globalPoints::addSendTransform
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:" << globalTransforms_.processor(info[i])
104  // << nl
105  // << " index:" << globalTransforms_.index(info[i]) << nl
106  // << " trafo:"
107  // << globalTransforms_.decodeTransformIndex
108  // (globalTransforms_.transformIndex(info[i]))
109  // << endl;
110 
111  sendInfo[i] = globalTransforms_.encode
112  (
113  globalTransforms_.processor(info[i]),
114  globalTransforms_.index(info[i]),
115  globalTransforms_.addToTransformIndex
116  (
117  globalTransforms_.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 void Foam::globalPoints::addToSend
129 (
130  const polyPatch& pp,
131  const label patchPointi,
132  const labelPairList& knownInfo,
133 
134  DynamicList<label>& patchFaces,
135  DynamicList<label>& indexInFace,
136  DynamicList<labelPairList>& allInfo
137 ) const
138 {
139  // Collect all topological information about a point on a patch. (this
140  // information is the patch faces using the point and the relative position
141  // of the point in the face)
142 
143  const label meshPointi = pp.meshPoints()[patchPointi];
144 
145  // Add all faces using the point so we are sure we find it on the
146  // other side.
147  const labelList& pFaces = pp.pointFaces()[patchPointi];
148 
149  for (const label patchFacei : pFaces)
150  {
151  const face& f = pp[patchFacei];
152 
153  patchFaces.append(patchFacei);
154  indexInFace.append(f.find(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  bool infoChanged = false;
280 
281  // Get the index into the procPoints list.
282  const auto iter = meshToProcPoint_.cfind(localPointi);
283 
284  if (iter.good())
285  {
286  if (mergeInfo(nbrInfo, localPointi, procPoints_[iter.val()]))
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  bool infoChanged = false;
329 
330  // Get the index into the procPoints list.
331  const auto iter = meshToProcPoint_.find(localPointi);
332 
333  if (iter.good())
334  {
335  if (mergeInfo(nbrInfo, localPointi, procPoints_[iter.val()]))
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  // Reset send/recv information
491  pBufs.clear();
492 
493  // Information to send:
494 
495  // The patch face
496  DynamicList<label> patchFaces;
497 
498  // Index in patch face
499  DynamicList<label> indexInFace;
500 
501  // All information I currently hold about the patchPoint
502  DynamicList<labelPairList> allInfo;
503 
504 
505  // Reduce communication by only sending non-zero data,
506  // but with multiply-connected processor/processor
507  // (eg, processorCyclic) also need to send zero information
508  // to keep things synchronised
509 
510  // Has non-zero data sent
511  Map<int> isActiveSend(0);
512 
513  if (UPstream::parRun())
514  {
515  isActiveSend.resize(2*min(patches.size(),pBufs.nProcs()));
516  }
517 
518  forAll(patches, patchi)
519  {
520  const polyPatch& pp = patches[patchi];
521 
522  // mergeSeparated=true : send from all processor patches
523  // =false: send from ones without transform
524 
525  if
526  (
527  (UPstream::parRun() && isA<processorPolyPatch>(pp))
528  && (mergeSeparated || patchInfo[patchi].first() == -1)
529  )
530  {
531  const auto& procPatch = refCast<const processorPolyPatch>(pp);
532  const label nbrProci = procPatch.neighbProcNo();
533 
534  patchFaces.clear();
535  patchFaces.reserve(pp.nPoints());
536 
537  indexInFace.clear();
538  indexInFace.reserve(pp.nPoints());
539 
540  allInfo.clear();
541  allInfo.reserve(pp.nPoints());
542 
543  // Now collect information on all points mentioned in
544  // changedPoints. Note that these points only should occur on
545  // processorPatches (or rather this is a limitation!).
546 
547  const labelList& meshPoints = pp.meshPoints();
548 
549  forAll(meshPoints, patchPointi)
550  {
551  label meshPointi = meshPoints[patchPointi];
552  label localPointi = meshToLocalPoint
553  (
554  meshToPatchPoint,
555  meshPointi
556  );
557 
558  if (changedPoints.found(localPointi))
559  {
560  label index = meshToProcPoint_[localPointi];
561 
562  const labelPairList& knownInfo = procPoints_[index];
563 
564  // Add my information about localPointi to the
565  // send buffers. Encode the transformation
566  addToSend
567  (
568  pp,
569  patchPointi,
570  knownInfo,
571 
572  patchFaces,
573  indexInFace,
574  allInfo
575  );
576  }
577  }
578 
579 
580  // Send to neighbour
581  {
582  UOPstream toNbr(nbrProci, pBufs);
583  toNbr << patchFaces << indexInFace << allInfo;
584 
585  // Record if send is required (data are non-zero)
586  isActiveSend(nbrProci) |= int(!patchFaces.empty());
587 
588  if (debug)
589  {
590  Pout<< "Sending from " << pp.name() << " to proc:"
591  << nbrProci << " point information:"
592  << patchFaces.size() << endl;
593  }
594  }
595  }
596  }
597 
598  // Eliminate unnecessary sends
599  forAllConstIters(isActiveSend, iter)
600  {
601  if (!iter.val())
602  {
603  pBufs.clearSend(iter.key());
604  }
605  }
606 }
607 
608 
609 void Foam::globalPoints::receivePatchPoints
610 (
611  const bool mergeSeparated,
612  const Map<label>& meshToPatchPoint,
613  const labelList& patchToMeshPoint,
614  PstreamBuffers& pBufs,
615  labelHashSet& changedPoints
616 )
617 {
618  // Receive all my neighbours' information and merge with mine.
619  // After finishing will have updated
620  // - procPoints_ : all neighbour information merged in.
621  // - meshToProcPoint_
622  // - changedPoints: all points for which something changed.
623 
624  const polyBoundaryMesh& patches = mesh_.boundaryMesh();
625  const labelPairList& patchInfo = globalTransforms_.patchTransformSign();
626 
627  // Reset changed points
628  changedPoints.clear();
629 
630  forAll(patches, patchi)
631  {
632  const polyPatch& pp = patches[patchi];
633 
634  if
635  (
636  (UPstream::parRun() && isA<processorPolyPatch>(pp))
637  && (mergeSeparated || patchInfo[patchi].first() == -1)
638  )
639  {
640  const auto& procPatch = refCast<const processorPolyPatch>(pp);
641  const label nbrProci = procPatch.neighbProcNo();
642 
643  if (!pBufs.recvDataCount(nbrProci))
644  {
645  // Nothing to receive
646  continue;
647  }
648 
649  labelList patchFaces;
650  labelList indexInFace;
651  List<labelPairList> nbrInfo;
652 
653  {
654  UIPstream fromNbr(nbrProci, pBufs);
655  fromNbr >> patchFaces >> indexInFace >> nbrInfo;
656  }
657 
658  if (debug)
659  {
660  Pout<< " On " << pp.name()
661  << " Received from "
662  << nbrProci << " point information:"
663  << patchFaces.size() << endl;
664  }
665 
666  forAll(patchFaces, i)
667  {
668  const face& f = pp[patchFaces[i]];
669 
670  // Get index in this face from index on face on other side.
671  label index = (f.size() - indexInFace[i]) % f.size();
672 
673  // Get the meshpoint on my side
674  label meshPointi = f[index];
675 
676  label localPointi = meshToLocalPoint
677  (
678  meshToPatchPoint,
679  meshPointi
680  );
681 
682  if (mergeInfo(nbrInfo[i], localPointi))
683  {
684  changedPoints.insert(localPointi);
685  }
686  }
687  }
688  else if
689  (
690  (
691  isA<cyclicPolyPatch>(pp)
692  && refCast<const cyclicPolyPatch>(pp).owner()
693  )
694  && (mergeSeparated || patchInfo[patchi].first() == -1)
695  )
696  {
697  // Handle cyclics: send lower half to upper half and vice versa.
698  // Or since they both are in memory just do it point by point.
699 
700  const cyclicPolyPatch& cycPatch =
701  refCast<const cyclicPolyPatch>(pp);
702 
703  //Pout<< "Patch:" << patchi << " name:" << pp.name() << endl;
704 
705  const labelList& meshPoints = pp.meshPoints();
706  const labelList coupledMeshPoints(reverseMeshPoints(cycPatch));
707 
708  forAll(meshPoints, i)
709  {
710  label meshPointA = meshPoints[i];
711  label meshPointB = coupledMeshPoints[i];
712 
713  if (meshPointA != meshPointB)
714  {
715  //Pout<< "Connection between point " << meshPointA
716  // << " at " << mesh_.points()[meshPointA]
717  // << " and " << meshPointB
718  // << " at " << mesh_.points()[meshPointB] << endl;
719 
720  label localA = meshToLocalPoint
721  (
722  meshToPatchPoint,
723  meshPointA
724  );
725  label localB = meshToLocalPoint
726  (
727  meshToPatchPoint,
728  meshPointB
729  );
730 
731 
732  // Do we have information on pointA?
733  const auto procPointA = meshToProcPoint_.cfind(localA);
734 
735  if (procPointA.good())
736  {
737  const labelPairList infoA = addSendTransform
738  (
739  cycPatch.index(),
740  procPoints_[procPointA()]
741  );
742 
743  if (mergeInfo(infoA, localB))
744  {
745  changedPoints.insert(localB);
746  }
747  }
748 
749  // Same for info on pointB
750  const auto procPointB = meshToProcPoint_.cfind(localB);
751 
752  if (procPointB.good())
753  {
754  const labelPairList infoB = addSendTransform
755  (
756  cycPatch.neighbPatchID(),
757  procPoints_[procPointB()]
758  );
759 
760  if (mergeInfo(infoB, localA))
761  {
762  changedPoints.insert(localA);
763  }
764  }
765  }
766  }
767  }
768  }
769 }
770 
771 
772 void Foam::globalPoints::remove
773 (
774  const labelList& patchToMeshPoint,
775  const Map<label>& directNeighbours
776 )
777 {
778  // Remove entries which are handled by normal face-face communication. I.e.
779  // those points where the equivalence list is only me and my (face)neighbour
780 
781  // Save old ones.
782  Map<label> oldMeshToProcPoint(std::move(meshToProcPoint_));
783  meshToProcPoint_.resize(oldMeshToProcPoint.size());
784  DynamicList<labelPairList> oldProcPoints(std::move(procPoints_));
785  procPoints_.setCapacity(oldProcPoints.size());
786 
787  // Go through all equivalences
788  forAllConstIters(oldMeshToProcPoint, iter)
789  {
790  const label localPointi = iter.key();
791  const labelPairList& pointInfo = oldProcPoints[iter.val()];
792 
793  if (pointInfo.size() == 2)
794  {
795  // I will be in this equivalence list.
796  // Check whether my direct (=face) neighbour
797  // is in it. This would be an ordinary connection and can be
798  // handled by normal face-face connectivity.
799 
800  label proc0 = globalTransforms_.processor(pointInfo[0]);
801  label proc1 = globalTransforms_.processor(pointInfo[1]);
802 
803  if
804  (
805  (
806  proc0 == Pstream::myProcNo()
807  && directNeighbours.found
808  (
809  globalTransforms_.index(pointInfo[0])
810  )
811  )
812  || (
813  proc1 == Pstream::myProcNo()
814  && directNeighbours.found
815  (
816  globalTransforms_.index(pointInfo[1])
817  )
818  )
819  )
820  {
821  // Normal faceNeighbours
822  if (proc0 == Pstream::myProcNo())
823  {
824  //Pout<< "Removing direct neighbour:"
825  // << mesh_.points()
826  // [globalTransforms_.index(pointInfo[0])]
827  // << endl;
828  }
829  else if (proc1 == Pstream::myProcNo())
830  {
831  //Pout<< "Removing direct neighbour:"
832  // << mesh_.points()
833  // [globalTransforms_.index(pointInfo[1])]
834  // << endl;
835  }
836  }
837  else
838  {
839  // This condition will be very rare: points are used by
840  // two processors which are not face-face connected.
841  // e.g.
842  // +------+------+
843  // | wall | B |
844  // +------+------+
845  // | A | wall |
846  // +------+------+
847  // Processor A and B share a point. Note that this only will
848  // be found if the two domains are face connected at all
849  // (not shown in the picture)
850 
851  meshToProcPoint_.insert(localPointi, procPoints_.size());
852  procPoints_.append(pointInfo);
853  }
854  }
855  else if (pointInfo.size() == 1)
856  {
857  // This happens for 'wedge' like cyclics where the two halves
858  // come together in the same point so share the same meshPoint.
859  // So this meshPoint will have info of size one only.
860  if
861  (
862  globalTransforms_.processor(pointInfo[0])
863  != Pstream::myProcNo()
864  || !directNeighbours.found
865  (
866  globalTransforms_.index(pointInfo[0])
867  )
868  )
869  {
870  meshToProcPoint_.insert(localPointi, procPoints_.size());
871  procPoints_.append(pointInfo);
872  }
873  }
874  else
875  {
876  meshToProcPoint_.insert(localPointi, procPoints_.size());
877  procPoints_.append(pointInfo);
878  }
879  }
880 
881  procPoints_.shrink();
882  meshToProcPoint_.resize(2*procPoints_.size());
883 }
884 
885 
886 Foam::labelList Foam::globalPoints::reverseMeshPoints
887 (
888  const cyclicPolyPatch& pp
889 )
890 {
891  const cyclicPolyPatch& nbrPatch = pp.neighbPatch();
892 
893  faceList masterFaces(nbrPatch.size());
894 
895  forAll(nbrPatch, facei)
896  {
897  masterFaces[facei] = nbrPatch[facei].reverseFace();
898  }
899 
900  return primitiveFacePatch
901  (
902  masterFaces,
903  nbrPatch.points()
904  ).meshPoints();
905 }
906 
907 
908 void Foam::globalPoints::calculateSharedPoints
909 (
910  const Map<label>& meshToPatchPoint, // from mesh point to local numbering
911  const labelList& patchToMeshPoint, // from local numbering to mesh point
912  const bool keepAllPoints,
913  const bool mergeSeparated
914 )
915 {
916  if (debug)
917  {
918  Pout<< "globalPoints::calculateSharedPoints(..) : "
919  << "doing processor to processor communication to get sharedPoints"
920  << endl
921  << " keepAllPoints :" << keepAllPoints << endl
922  << " mergeSeparated:" << mergeSeparated << endl
923  << endl;
924  }
925 
926 
927  labelHashSet changedPoints(2*nPatchPoints_);
928 
929  // Initialize procPoints with my patch points. Keep track of points
930  // inserted (in changedPoints)
931  // There are two possible forms of this:
932  // - initialize with all patch points (allPoints = true). This causes all
933  // patch points to be exchanged so a lot of information gets stored and
934  // transferred. This all gets filtered out later when removing the
935  // equivalence lists of size 2.
936  // - initialize with boundary points of patches only (allPoints = false).
937  // This should work for all decompositions except extreme ones where a
938  // shared point is not on the boundary of any processor patches using it.
939  // This would happen if a domain was pinched such that two patches share
940  // a point or edge.
941  initOwnPoints(meshToPatchPoint, true, changedPoints);
942 
943  // Note: to use 'scheduled' would have to intersperse send and receive.
944  // So for now just use nonBlocking. Also globalPoints itself gets
945  // constructed by mesh.globalData().patchSchedule() so creates a loop.
946  PstreamBuffers pBufs
947  (
948  (
952  )
953  );
954 
955  // Don't clear storage on persistent buffer
956  pBufs.allowClearRecv(false);
957 
958  // Do one exchange iteration to get neighbour points.
959  {
960  sendPatchPoints
961  (
962  mergeSeparated,
963  meshToPatchPoint,
964  pBufs,
965  changedPoints
966  );
967 
968  pBufs.finishedSends();
969 
970  receivePatchPoints
971  (
972  mergeSeparated,
973  meshToPatchPoint,
974  patchToMeshPoint,
975  pBufs,
976  changedPoints
977  );
978  }
979 
980  // Save neighbours reachable through face-face communication.
981  Map<label> neighbourList;
982  if (!keepAllPoints)
983  {
984  neighbourList = meshToProcPoint_;
985  }
986 
987  // Exchange until nothing changes on any processors.
988 
989  do
990  {
991  sendPatchPoints
992  (
993  mergeSeparated,
994  meshToPatchPoint,
995  pBufs,
996  changedPoints
997  );
998 
999  pBufs.finishedSends();
1000 
1001  receivePatchPoints
1002  (
1003  mergeSeparated,
1004  meshToPatchPoint,
1005  patchToMeshPoint,
1006  pBufs,
1007  changedPoints
1008  );
1009 
1010  } while (returnReduceOr(changedPoints.size()));
1011 
1012 
1013  //Pout<< "**ALL** connected points:" << endl;
1014  //forAllConstIters(meshToProcPoint_, iter)
1015  //{
1016  // label localI = iter.key();
1017  // const labelPairList& pointInfo = procPoints_[iter.val()];
1018  // Pout<< "pointi:" << localI << " index:" << iter.val()
1019  // << " coord:"
1020  // << mesh_.points()[localToMeshPoint(patchToMeshPoint, localI)]
1021  // << endl;
1022  // printProcPoints(patchToMeshPoint, pointInfo);
1023  // Pout<< endl;
1024  //}
1025 
1026 
1027  // Remove direct neighbours from point equivalences.
1028  if (!keepAllPoints)
1029  {
1030  remove(patchToMeshPoint, neighbourList);
1031  }
1032 
1033 
1034  // Sort procPoints in incremental order. This will make
1035  // the master the first element on all processors.
1036  // Note: why not sort in decreasing order? Give more work to higher
1037  // processors.
1038  forAllConstIters(meshToProcPoint_, iter)
1039  {
1040  labelPairList& pointInfo = procPoints_[iter.val()];
1041  sort(pointInfo, globalIndexAndTransform::less(globalTransforms_));
1042  }
1043 
1044 
1045  // We now have - in procPoints_ - a list of points which are shared between
1046  // multiple processors. Filter into non-transformed and transformed
1047  // connections.
1048 
1049  pointPoints_.setSize(globalIndices_.localSize());
1050  List<labelPairList> transformedPoints(globalIndices_.localSize());
1051 
1052  forAllConstIters(meshToProcPoint_, iter)
1053  {
1054  const labelPairList& pointInfo = procPoints_[iter.val()];
1055 
1056  if (pointInfo.size() >= 2)
1057  {
1058  // Since sorted master point is the first element
1059  const labelPair& masterInfo = pointInfo[0];
1060 
1061  if
1062  (
1063  (
1064  globalTransforms_.processor(masterInfo)
1065  == Pstream::myProcNo()
1066  )
1067  && (globalTransforms_.index(masterInfo) == iter.key())
1068  )
1069  {
1070  labelList& pPoints = pointPoints_[iter.key()];
1071  pPoints.setSize(pointInfo.size()-1);
1072 
1073  labelPairList& trafoPPoints = transformedPoints[iter.key()];
1074  trafoPPoints.setSize(pointInfo.size()-1);
1075 
1076  label nonTransformI = 0;
1077  label transformI = 0;
1078 
1079  for (label i = 1; i < pointInfo.size(); i++)
1080  {
1081  const labelPair& info = pointInfo[i];
1082  label proci = globalTransforms_.processor(info);
1083  label index = globalTransforms_.index(info);
1084  label transform = globalTransforms_.transformIndex
1085  (
1086  info
1087  );
1088 
1089  if (transform == globalTransforms_.nullTransformIndex())
1090  {
1091  pPoints[nonTransformI++] = globalIndices_.toGlobal
1092  (
1093  proci,
1094  index
1095  );
1096  }
1097  else
1098  {
1099  trafoPPoints[transformI++] = info;
1100  }
1101  }
1102 
1103  pPoints.setSize(nonTransformI);
1104  trafoPPoints.setSize(transformI);
1105  }
1106  }
1107  }
1108 
1109 
1110  List<Map<label>> compactMap;
1111  map_.reset
1112  (
1113  new mapDistribute
1114  (
1115  globalIndices_,
1116  pointPoints_,
1117 
1118  globalTransforms_,
1119  transformedPoints,
1120  transformedPointPoints_,
1121 
1122  compactMap
1123  )
1124  );
1125 
1126  if (debug)
1127  {
1128  Pout<< "globalPoints::calculateSharedPoints(..) : "
1129  << "Finished global points" << endl;
1130  }
1131 }
1132 
1133 
1134 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
1135 
1136 Foam::globalPoints::globalPoints
1137 (
1138  const polyMesh& mesh,
1139  const bool keepAllPoints,
1140  const bool mergeSeparated
1141 )
1142 :
1143  mesh_(mesh),
1144  globalIndices_(mesh_.nPoints()),
1145  globalTransforms_(mesh),
1146  nPatchPoints_(countPatchPoints(mesh.boundaryMesh())),
1147  procPoints_(nPatchPoints_),
1148  meshToProcPoint_(nPatchPoints_)
1149 {
1150  // Empty patch maps to signal storing mesh point labels
1151  Map<label> meshToPatchPoint(0);
1152  labelList patchToMeshPoint(0);
1153 
1154  calculateSharedPoints
1155  (
1156  meshToPatchPoint,
1157  patchToMeshPoint,
1158  keepAllPoints,
1159  mergeSeparated
1160  );
1161 }
1162 
1163 
1164 Foam::globalPoints::globalPoints
1165 (
1166  const polyMesh& mesh,
1167  const indirectPrimitivePatch& coupledPatch,
1168  const bool keepAllPoints,
1169  const bool mergeSeparated
1170 )
1171 :
1172  mesh_(mesh),
1173  globalIndices_(coupledPatch.nPoints()),
1174  globalTransforms_(mesh),
1175  nPatchPoints_(coupledPatch.nPoints()),
1176  procPoints_(nPatchPoints_),
1177  meshToProcPoint_(nPatchPoints_)
1178 {
1179  calculateSharedPoints
1180  (
1181  coupledPatch.meshPointMap(),
1182  coupledPatch.meshPoints(),
1183  keepAllPoints,
1184  mergeSeparated
1185  );
1186 }
1187 
1188 
1189 // ************************************************************************* //
label nPoints() const
Number of points supporting patch faces.
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:116
label find(const T &val, label pos=0) const
Find index of the first occurrence of the value.
Definition: UList.C:204
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: BitOps.H:56
const labelList & boundaryPoints() const
Return list of boundary points, address into LOCAL point list.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:487
static bool & parRun() noexcept
Test if this a parallel run.
Definition: UPstream.H:1004
List< labelPair > labelPairList
List of labelPair.
Definition: labelPair.H:33
static int myProcNo(const label communicator=worldComm)
Rank of this process in the communicator (starting from masterNo()). Can be negative if the process i...
Definition: UPstream.H:1029
static bool less(const vector &x, const vector &y)
To compare normals.
const labelList & meshPoints() const
Return labelList of mesh points in patch.
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:414
HashSet< label, Hash< label > > labelHashSet
A HashSet of labels, uses label hasher.
Definition: HashSet.H:85
List< face > faceList
List of faces.
Definition: faceListFwd.H:39
A list of faces which address into the list of points.
const Map< label > & meshPointMap() const
Mesh point map.
void setSize(const label n)
Alias for resize()
Definition: List.H:289
dynamicFvMesh & mesh
"scheduled" : (MPI_Send, MPI_Recv)
label nPoints
void sort(UList< T > &list)
Sort the list.
Definition: UList.C:348
label size() const noexcept
The number of entries in the list.
Definition: UPtrListI.H:113
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:26
void reset(const dimensionSet &ds)
Copy assign the exponents from the dimensionSet.
Definition: dimensionSet.C:142
const labelListList & pointFaces() const
Return point-face addressing.
void clear()
Clear the patch list and all demand-driven data.
int debug
Static debugging option.
Pair< label > labelPair
A pair of labels.
Definition: Pair.H:51
defineTypeNameAndDebug(combustionModel, 0)
labelList f(nPoints)
PrimitivePatch< List< face >, const pointField & > primitiveFacePatch
A PrimitivePatch with List storage for the faces, const reference for the point field.
Info<< "Finished reading KIVA file"<< endl;cellShapeList cellShapes(nPoints);labelList cellZoning(nPoints, -1);const cellModel &hex=cellModel::ref(cellModel::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].reset(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
static commsTypes defaultCommsType
Default commsType.
Definition: UPstream.H:387
const polyBoundaryMesh & patches
"nonBlocking" : (MPI_Isend, MPI_Irecv)
tmp< pointField > allPoints(const Triangulation &t)
Extract all points in vertex-index order.
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:73
List< label > labelList
A List of labels.
Definition: List.H:62
dimensionSet transform(const dimensionSet &ds)
Return the argument; transformations do not change the dimensions.
Definition: dimensionSet.C:521
bool returnReduceOr(const bool value, const label comm=UPstream::worldComm)
Perform logical (or) MPI Allreduce on a copy. Uses UPstream::reduceOr.
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
uindirectPrimitivePatch pp(UIndirectList< face >(mesh.faces(), faceLabels), mesh.points())
Namespace for OpenFOAM.
forAllConstIters(mixture.phases(), phase)
Definition: pEqn.H:28