globalMeshData.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) 2015-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 "globalMeshData.H"
30 #include "globalPoints.H"
31 #include "polyMesh.H"
32 #include "mapDistribute.H"
33 #include "labelIOList.H"
34 #include "mergePoints.H"
35 #include "processorPolyPatch.H"
36 #include "processorTopologyNew.H"
38 #include "Pstream.H"
39 
40 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
41 
42 namespace Foam
43 {
44 defineTypeNameAndDebug(globalMeshData, 0);
45 
46 const scalar globalMeshData::matchTol_ = 1e-8;
47 
48 template<>
49 class minEqOp<labelPair>
50 {
51 public:
52  void operator()(labelPair& x, const labelPair& y) const
53  {
54  x[0] = min(x[0], y[0]);
55  x[1] = min(x[1], y[1]);
56  }
57 };
58 }
59 
60 
61 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
62 
63 void Foam::globalMeshData::initProcAddr()
64 {
65  processorPatchIndices_.resize_nocopy(mesh_.boundaryMesh().size());
66  processorPatchIndices_ = -1;
67 
68  processorPatchNeighbours_.resize_nocopy(mesh_.boundaryMesh().size());
69  processorPatchNeighbours_ = -1;
70 
71  // Construct processor patch indexing. processorPatchNeighbours_ only
72  // set if running in parallel!
73  processorPatches_.resize_nocopy(mesh_.boundaryMesh().size());
74 
75  label nNeighbours = 0;
76 
77  forAll(mesh_.boundaryMesh(), patchi)
78  {
79  if (isA<processorPolyPatch>(mesh_.boundaryMesh()[patchi]))
80  {
81  processorPatches_[nNeighbours] = patchi;
82  processorPatchIndices_[patchi] = nNeighbours++;
83  }
84  }
85  processorPatches_.resize(nNeighbours);
86 
87 
88  if (Pstream::parRun())
89  {
90  PstreamBuffers pBufs(Pstream::commsTypes::nonBlocking);
91 
92  // Send indices of my processor patches to my neighbours
93  for (const label patchi : processorPatches_)
94  {
95  UOPstream toNeighbour
96  (
97  refCast<const processorPolyPatch>
98  (
99  mesh_.boundaryMesh()[patchi]
100  ).neighbProcNo(),
101  pBufs
102  );
103 
104  toNeighbour << processorPatchIndices_[patchi];
105  }
106 
107  pBufs.finishedSends();
108 
109  for (const label patchi : processorPatches_)
110  {
111  UIPstream fromNeighbour
112  (
113  refCast<const processorPolyPatch>
114  (
115  mesh_.boundaryMesh()[patchi]
116  ).neighbProcNo(),
117  pBufs
118  );
119 
120  fromNeighbour >> processorPatchNeighbours_[patchi];
121  }
122  }
123 }
124 
125 
126 void Foam::globalMeshData::calcSharedPoints() const
127 {
128  if
129  (
130  nGlobalPoints_ != -1
131  || sharedPointLabelsPtr_
132  || sharedPointAddrPtr_
133  )
134  {
136  << "Shared point addressing already done" << abort(FatalError);
137  }
138 
139  // Calculate all shared points (exclude points that are only
140  // on two coupled patches). This does all the hard work.
141  const globalPoints parallelPoints(mesh_, false, true);
142 
143  // Count the number of master points
144  label nMaster = 0;
145  forAll(parallelPoints.pointPoints(), i)
146  {
147  const labelList& pPoints = parallelPoints.pointPoints()[i];
148  const labelList& transPPoints =
149  parallelPoints.transformedPointPoints()[i];
150 
151  if (pPoints.size()+transPPoints.size() > 0)
152  {
153  nMaster++;
154  }
155  }
156 
157  // Allocate global numbers
158  const globalIndex masterNumbering(nMaster);
159 
160  nGlobalPoints_ = masterNumbering.totalSize();
161 
162 
163  // Push master number to slaves
164  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
165  // 1. Fill master and slave slots
166  nMaster = 0;
167  labelList master(parallelPoints.map().constructSize(), -1);
168  forAll(parallelPoints.pointPoints(), i)
169  {
170  const labelList& pPoints = parallelPoints.pointPoints()[i];
171  const labelList& transPPoints =
172  parallelPoints.transformedPointPoints()[i];
173 
174  if (pPoints.size()+transPPoints.size() > 0)
175  {
176  master[i] = masterNumbering.toGlobal(nMaster);
177  forAll(pPoints, j)
178  {
179  master[pPoints[j]] = master[i];
180  }
181  forAll(transPPoints, j)
182  {
183  master[transPPoints[j]] = master[i];
184  }
185  nMaster++;
186  }
187  }
188 
189 
190  // 2. Push slave slots back to local storage on originating processor
191  // For all the four types of points:
192  // - local master : already set
193  // - local transformed slave point : the reverse transform at
194  // reverseDistribute will have copied it back to its originating local
195  // point
196  // - remote untransformed slave point : sent back to originating processor
197  // - remote transformed slave point : the reverse transform will
198  // copy it back into the remote slot which then gets sent back to
199  // originating processor
200 
201  parallelPoints.map().reverseDistribute
202  (
203  parallelPoints.map().constructSize(),
204  master
205  );
206 
207 
208  // Collect all points that are a master or refer to a master.
209  nMaster = 0;
210  forAll(parallelPoints.pointPoints(), i)
211  {
212  if (master[i] != -1)
213  {
214  nMaster++;
215  }
216  }
217 
218  sharedPointLabelsPtr_.reset(new labelList(nMaster));
219  labelList& sharedPointLabels = sharedPointLabelsPtr_();
220  sharedPointAddrPtr_.reset(new labelList(nMaster));
221  labelList& sharedPointAddr = sharedPointAddrPtr_();
222  nMaster = 0;
223 
224  forAll(parallelPoints.pointPoints(), i)
225  {
226  if (master[i] != -1)
227  {
228  // I am master or slave
229  sharedPointLabels[nMaster] = i;
230  sharedPointAddr[nMaster] = master[i];
231  nMaster++;
232  }
233  }
234 
235  if (debug)
236  {
237  Pout<< "globalMeshData : nGlobalPoints_:" << nGlobalPoints_ << nl
238  << "globalMeshData : sharedPointLabels_:"
239  << sharedPointLabelsPtr_().size() << nl
240  << "globalMeshData : sharedPointAddr_:"
241  << sharedPointAddrPtr_().size() << endl;
242  }
243 }
244 
245 
246 void Foam::globalMeshData::countSharedEdges
247 (
248  const EdgeMap<labelList>& procSharedEdges,
249  EdgeMap<label>& globalShared,
250  label& sharedEdgeI
251 )
252 {
253  // Count occurrences of procSharedEdges in global shared edges table.
254  forAllConstIters(procSharedEdges, iter)
255  {
256  const edge& e = iter.key();
257 
258  auto globalFnd = globalShared.find(e);
259 
260  if (globalFnd.found())
261  {
262  if (globalFnd() == -1)
263  {
264  // Second time occurrence of this edge.
265  // Assign proper edge label.
266  globalFnd() = sharedEdgeI++;
267  }
268  }
269  else
270  {
271  // First time occurrence of this edge. Check how many we are adding.
272  if (iter().size() == 1)
273  {
274  // Only one edge. Mark with special value.
275  globalShared.insert(e, -1);
276  }
277  else
278  {
279  // Edge used more than once (even by local shared edges alone)
280  // so allocate proper shared edge label.
281  globalShared.insert(e, sharedEdgeI++);
282  }
283  }
284  }
285 }
286 
287 
288 void Foam::globalMeshData::calcSharedEdges() const
289 {
290  // Shared edges are shared between multiple processors. By their nature both
291  // of their endpoints are shared points. (but not all edges using two shared
292  // points are shared edges! There might e.g. be an edge between two
293  // unrelated clusters of shared points)
294 
295  if
296  (
297  nGlobalEdges_ != -1
298  || sharedEdgeLabelsPtr_
299  || sharedEdgeAddrPtr_
300  )
301  {
303  << "Shared edge addressing already done" << abort(FatalError);
304  }
305 
306 
307  const labelList& sharedPtAddr = sharedPointAddr();
308  const labelList& sharedPtLabels = sharedPointLabels();
309 
310  // Since don't want to construct pointEdges for whole mesh create
311  // Map for all shared points.
312  Map<label> meshToShared(2*sharedPtLabels.size());
313  forAll(sharedPtLabels, i)
314  {
315  meshToShared.insert(sharedPtLabels[i], i);
316  }
317 
318  // Find edges using shared points. Store correspondence to local edge
319  // numbering. Note that multiple local edges can have the same shared
320  // points! (for cyclics or separated processor patches)
321  EdgeMap<labelList> localShared(2*sharedPtAddr.size());
322 
323  const edgeList& edges = mesh_.edges();
324 
325  forAll(edges, edgeI)
326  {
327  const edge& e = edges[edgeI];
328 
329  const auto e0Fnd = meshToShared.cfind(e[0]);
330 
331  if (e0Fnd.found())
332  {
333  const auto e1Fnd = meshToShared.cfind(e[1]);
334 
335  if (e1Fnd.found())
336  {
337  // Found edge which uses shared points. Probably shared.
338 
339  // Construct the edge in shared points (or rather global indices
340  // of the shared points)
341  edge sharedEdge
342  (
343  sharedPtAddr[e0Fnd()],
344  sharedPtAddr[e1Fnd()]
345  );
346 
347  auto iter = localShared.find(sharedEdge);
348 
349  if (!iter.found())
350  {
351  // First occurrence of this point combination. Store.
352  localShared.insert(sharedEdge, labelList(1, edgeI));
353  }
354  else
355  {
356  // Add this edge to list of edge labels.
357  labelList& edgeLabels = iter();
358 
359  const label sz = edgeLabels.size();
360  edgeLabels.setSize(sz+1);
361  edgeLabels[sz] = edgeI;
362  }
363  }
364  }
365  }
366 
367 
368  // Now we have a table on every processors which gives its edges which use
369  // shared points. Send this all to the master and have it allocate
370  // global edge numbers for it. But only allocate a global edge number for
371  // edge if it is used more than once!
372  // Note that we are now sending the whole localShared to the master whereas
373  // we only need the local count (i.e. the number of times a global edge is
374  // used). But then this only gets done once so not too bothered about the
375  // extra global communication.
376 
377  EdgeMap<label> globalShared(nGlobalPoints());
378 
379  if (Pstream::master())
380  {
381  label sharedEdgeI = 0;
382 
383  // Merge my shared edges into the global list
384  if (debug)
385  {
386  Pout<< "globalMeshData::calcSharedEdges : Merging in from proc0 : "
387  << localShared.size() << endl;
388  }
389  countSharedEdges(localShared, globalShared, sharedEdgeI);
390 
391  // Receive data and insert
392  if (Pstream::parRun())
393  {
394  for (const int proci : Pstream::subProcs())
395  {
396  // Receive the edges using shared points from the slave.
397  IPstream fromProc(Pstream::commsTypes::blocking, proci);
398  EdgeMap<labelList> procSharedEdges(fromProc);
399 
400  if (debug)
401  {
402  Pout<< "globalMeshData::calcSharedEdges : "
403  << "Merging in from proc"
404  << proci << " : " << procSharedEdges.size()
405  << endl;
406  }
407  countSharedEdges(procSharedEdges, globalShared, sharedEdgeI);
408  }
409  }
410 
411  // Now our globalShared should have some edges with -1 as edge label
412  // These were only used once so are not proper shared edges.
413  // Remove them.
414  {
415  EdgeMap<label> oldSharedEdges(globalShared);
416 
417  globalShared.clear();
418 
419  forAllConstIters(oldSharedEdges, iter)
420  {
421  if (iter() != -1)
422  {
423  globalShared.insert(iter.key(), iter());
424  }
425  }
426  if (debug)
427  {
428  Pout<< "globalMeshData::calcSharedEdges : Filtered "
429  << oldSharedEdges.size()
430  << " down to " << globalShared.size() << endl;
431  }
432  }
433  }
434  else
435  {
436  if (Pstream::parRun())
437  {
438  // Send local edges to master
439  OPstream toMaster
440  (
443  );
444  toMaster << localShared;
445  }
446  }
447 
448  // Broadcast: merged edges to all
449  Pstream::broadcast(globalShared); // == worldComm;
450 
451 
452  // Now use the global shared edges list (globalShared) to classify my local
453  // ones (localShared)
454 
455  nGlobalEdges_ = globalShared.size();
456 
457  DynamicList<label> dynSharedEdgeLabels(globalShared.size());
458  DynamicList<label> dynSharedEdgeAddr(globalShared.size());
459 
460  forAllConstIters(localShared, iter)
461  {
462  const edge& e = iter.key();
463 
464  const auto edgeFnd = globalShared.cfind(e);
465 
466  if (edgeFnd.found())
467  {
468  // My local edge is indeed a shared one. Go through all local edge
469  // labels with this point combination.
470  const labelList& edgeLabels = iter();
471 
472  for (const label edgei : edgeLabels)
473  {
474  // Store label of local mesh edge
475  dynSharedEdgeLabels.append(edgei);
476 
477  // Store label of shared edge
478  dynSharedEdgeAddr.append(edgeFnd());
479  }
480  }
481  }
482 
483 
484  sharedEdgeLabelsPtr_.reset(new labelList());
485  labelList& sharedEdgeLabels = sharedEdgeLabelsPtr_();
486  sharedEdgeLabels.transfer(dynSharedEdgeLabels);
487 
488  sharedEdgeAddrPtr_.reset(new labelList());
489  labelList& sharedEdgeAddr = sharedEdgeAddrPtr_();
490  sharedEdgeAddr.transfer(dynSharedEdgeAddr);
491 
492  if (debug)
493  {
494  Pout<< "globalMeshData : nGlobalEdges_:" << nGlobalEdges_ << nl
495  << "globalMeshData : sharedEdgeLabels:" << sharedEdgeLabels.size()
496  << nl
497  << "globalMeshData : sharedEdgeAddr:" << sharedEdgeAddr.size()
498  << endl;
499  }
500 }
501 
502 
503 void Foam::globalMeshData::calcGlobalPointSlaves() const
504 {
505  if (debug)
506  {
507  Pout<< "globalMeshData::calcGlobalPointSlaves() :"
508  << " calculating coupled master to slave point addressing."
509  << endl;
510  }
511 
512  // Calculate connected points for master points.
513  globalPoints globalData(mesh_, coupledPatch(), true, true);
514 
515  globalPointSlavesPtr_.reset
516  (
517  new labelListList
518  (
519  std::move(globalData.pointPoints())
520  )
521  );
522  globalPointTransformedSlavesPtr_.reset
523  (
524  new labelListList
525  (
526  std::move(globalData.transformedPointPoints())
527  )
528  );
529 
530  globalPointSlavesMapPtr_.reset
531  (
532  new mapDistribute
533  (
534  std::move(globalData.map())
535  )
536  );
537 }
538 
539 
540 void Foam::globalMeshData::calcPointConnectivity
541 (
542  List<labelPairList>& allPointConnectivity
543 ) const
544 {
545  const globalIndexAndTransform& transforms = globalTransforms();
546  const labelListList& slaves = globalPointSlaves();
547  const labelListList& transformedSlaves = globalPointTransformedSlaves();
548 
549 
550  // Create field with my local data
551  labelPairList myData(globalPointSlavesMap().constructSize());
552  forAll(slaves, pointi)
553  {
554  myData[pointi] = transforms.encode
555  (
557  pointi,
558  transforms.nullTransformIndex()
559  );
560  }
561  // Send to master
562  globalPointSlavesMap().distribute(myData);
563 
564 
565  // String of connected points with their transform
566  allPointConnectivity.setSize(globalPointSlavesMap().constructSize());
567  allPointConnectivity = labelPairList(0);
568 
569  // Pass1: do the master points since these also update local slaves
570  // (e.g. from local cyclics)
571  forAll(slaves, pointi)
572  {
573  // Reconstruct string of connected points
574  const labelList& pSlaves = slaves[pointi];
575  const labelList& pTransformSlaves = transformedSlaves[pointi];
576 
577  if (pSlaves.size()+pTransformSlaves.size())
578  {
579  labelPairList& pConnectivity = allPointConnectivity[pointi];
580 
581  pConnectivity.setSize(1+pSlaves.size()+pTransformSlaves.size());
582  label connI = 0;
583 
584  // Add myself
585  pConnectivity[connI++] = myData[pointi];
586  // Add untransformed points
587  forAll(pSlaves, i)
588  {
589  pConnectivity[connI++] = myData[pSlaves[i]];
590  }
591  // Add transformed points.
592  forAll(pTransformSlaves, i)
593  {
594  // Get transform from index
595  label transformI = globalPointSlavesMap().whichTransform
596  (
597  pTransformSlaves[i]
598  );
599  // Add transform to connectivity
600  const labelPair& n = myData[pTransformSlaves[i]];
601  label proci = transforms.processor(n);
602  label index = transforms.index(n);
603  pConnectivity[connI++] = transforms.encode
604  (
605  proci,
606  index,
607  transformI
608  );
609  }
610 
611  // Put back in slots
612  forAll(pSlaves, i)
613  {
614  allPointConnectivity[pSlaves[i]] = pConnectivity;
615  }
616  forAll(pTransformSlaves, i)
617  {
618  allPointConnectivity[pTransformSlaves[i]] = pConnectivity;
619  }
620  }
621  }
622 
623 
624  // Pass2: see if anything is still unset (should not be the case)
625  forAll(slaves, pointi)
626  {
627  labelPairList& pConnectivity = allPointConnectivity[pointi];
628 
629  if (pConnectivity.size() == 0)
630  {
631  pConnectivity.setSize(1, myData[pointi]);
632  }
633  }
634 
635 
636  globalPointSlavesMap().reverseDistribute
637  (
638  slaves.size(),
639  allPointConnectivity
640  );
641 }
642 
643 
644 void Foam::globalMeshData::calcGlobalPointEdges
645 (
646  labelListList& globalPointEdges,
647  List<labelPairList>& globalPointPoints
648 ) const
649 {
650  const edgeList& edges = coupledPatch().edges();
651  const labelListList& pointEdges = coupledPatch().pointEdges();
652  const globalIndex& globalEdgeNumbers = globalEdgeNumbering();
653  const labelListList& slaves = globalPointSlaves();
654  const labelListList& transformedSlaves = globalPointTransformedSlaves();
655  const globalIndexAndTransform& transforms = globalTransforms();
656 
657 
658  // Create local version
659  globalPointEdges.setSize(globalPointSlavesMap().constructSize());
660  globalPointPoints.setSize(globalPointSlavesMap().constructSize());
661  forAll(pointEdges, pointi)
662  {
663  const labelList& pEdges = pointEdges[pointi];
664  globalPointEdges[pointi] = globalEdgeNumbers.toGlobal(pEdges);
665 
666  labelPairList& globalPPoints = globalPointPoints[pointi];
667  globalPPoints.setSize(pEdges.size());
668  forAll(pEdges, i)
669  {
670  label otherPointi = edges[pEdges[i]].otherVertex(pointi);
671  globalPPoints[i] = transforms.encode
672  (
674  otherPointi,
675  transforms.nullTransformIndex()
676  );
677  }
678  }
679 
680  // Pull slave data to master. Dummy transform.
681  globalPointSlavesMap().distribute(globalPointEdges);
682  globalPointSlavesMap().distribute(globalPointPoints);
683  // Add all pointEdges
684  forAll(slaves, pointi)
685  {
686  const labelList& pSlaves = slaves[pointi];
687  const labelList& pTransformSlaves = transformedSlaves[pointi];
688 
689  label n = 0;
690  forAll(pSlaves, i)
691  {
692  n += globalPointEdges[pSlaves[i]].size();
693  }
694  forAll(pTransformSlaves, i)
695  {
696  n += globalPointEdges[pTransformSlaves[i]].size();
697  }
698 
699  // Add all the point edges of the slaves to those of the (master) point
700  {
701  labelList& globalPEdges = globalPointEdges[pointi];
702  label sz = globalPEdges.size();
703  globalPEdges.setSize(sz+n);
704  forAll(pSlaves, i)
705  {
706  const labelList& otherData = globalPointEdges[pSlaves[i]];
707  forAll(otherData, j)
708  {
709  globalPEdges[sz++] = otherData[j];
710  }
711  }
712  forAll(pTransformSlaves, i)
713  {
714  const labelList& otherData =
715  globalPointEdges[pTransformSlaves[i]];
716  forAll(otherData, j)
717  {
718  globalPEdges[sz++] = otherData[j];
719  }
720  }
721 
722  // Put back in slots
723  forAll(pSlaves, i)
724  {
725  globalPointEdges[pSlaves[i]] = globalPEdges;
726  }
727  forAll(pTransformSlaves, i)
728  {
729  globalPointEdges[pTransformSlaves[i]] = globalPEdges;
730  }
731  }
732 
733 
734  // Same for corresponding pointPoints
735  {
736  labelPairList& globalPPoints = globalPointPoints[pointi];
737  label sz = globalPPoints.size();
738  globalPPoints.setSize(sz + n);
739 
740  // Add untransformed points
741  forAll(pSlaves, i)
742  {
743  const labelPairList& otherData = globalPointPoints[pSlaves[i]];
744  forAll(otherData, j)
745  {
746  globalPPoints[sz++] = otherData[j];
747  }
748  }
749  // Add transformed points.
750  forAll(pTransformSlaves, i)
751  {
752  // Get transform from index
753  label transformI = globalPointSlavesMap().whichTransform
754  (
755  pTransformSlaves[i]
756  );
757 
758  const labelPairList& otherData =
759  globalPointPoints[pTransformSlaves[i]];
760  forAll(otherData, j)
761  {
762  // Add transform to connectivity
763  const labelPair& n = otherData[j];
764  label proci = transforms.processor(n);
765  label index = transforms.index(n);
766  globalPPoints[sz++] = transforms.encode
767  (
768  proci,
769  index,
770  transformI
771  );
772  }
773  }
774 
775  // Put back in slots
776  forAll(pSlaves, i)
777  {
778  globalPointPoints[pSlaves[i]] = globalPPoints;
779  }
780  forAll(pTransformSlaves, i)
781  {
782  globalPointPoints[pTransformSlaves[i]] = globalPPoints;
783  }
784  }
785  }
786  // Push back
787  globalPointSlavesMap().reverseDistribute
788  (
789  slaves.size(),
790  globalPointEdges
791  );
792  // Push back
793  globalPointSlavesMap().reverseDistribute
794  (
795  slaves.size(),
796  globalPointPoints
797  );
798 }
799 
800 
801 Foam::label Foam::globalMeshData::findTransform
802 (
803  const labelPairList& info,
804  const labelPair& remotePoint,
805  const label localPoint
806 ) const
807 {
808  const globalIndexAndTransform& transforms = globalTransforms();
809 
810  const label remoteProci = transforms.processor(remotePoint);
811  const label remoteIndex = transforms.index(remotePoint);
812 
813  label remoteTransformI = -1;
814  label localTransformI = -1;
815  forAll(info, i)
816  {
817  label proci = transforms.processor(info[i]);
818  label pointi = transforms.index(info[i]);
819  label transformI = transforms.transformIndex(info[i]);
820 
821  if (proci == Pstream::myProcNo() && pointi == localPoint)
822  {
823  localTransformI = transformI;
824  //Pout<< "For local :" << localPoint
825  // << " found transform:" << localTransformI
826  // << endl;
827  }
828  if (proci == remoteProci && pointi == remoteIndex)
829  {
830  remoteTransformI = transformI;
831  //Pout<< "For remote:" << remotePoint
832  // << " found transform:" << remoteTransformI
833  // << " at index:" << i
834  // << endl;
835  }
836  }
837 
838  if (remoteTransformI == -1 || localTransformI == -1)
839  {
841  << "Problem. Cannot find " << remotePoint
842  << " or " << localPoint << " "
843  << coupledPatch().localPoints()[localPoint]
844  << " in " << info
845  << endl
846  << "remoteTransformI:" << remoteTransformI << endl
847  << "localTransformI:" << localTransformI
848  << abort(FatalError);
849  }
850 
851  return transforms.subtractTransformIndex
852  (
853  remoteTransformI,
854  localTransformI
855  );
856 }
857 
858 
859 void Foam::globalMeshData::calcGlobalEdgeSlaves() const
860 {
861  if (debug)
862  {
863  Pout<< "globalMeshData::calcGlobalEdgeSlaves() :"
864  << " calculating coupled master to slave edge addressing." << endl;
865  }
866 
867  const edgeList& edges = coupledPatch().edges();
868  const globalIndex& globalEdgeNumbers = globalEdgeNumbering();
869  const globalIndexAndTransform& transforms = globalTransforms();
870 
871 
872  // The whole problem with deducting edge-connectivity from
873  // point-connectivity is that one of the endpoints might be
874  // a local master but the other endpoint might not. So we first
875  // need to make sure that all points know about connectivity and
876  // the transformations.
877 
878 
879  // 1. collect point connectivity - basically recreating globalPoints output.
880  // All points will now have a string of coupled points. The transforms are
881  // in respect to the master.
882  List<labelPairList> allPointConnectivity;
883  calcPointConnectivity(allPointConnectivity);
884 
885 
886  // 2. Get all pointEdges and pointPoints
887  // Coupled point to global coupled edges and corresponding endpoint.
888  labelListList globalPointEdges;
889  List<labelPairList> globalPointPoints;
890  calcGlobalPointEdges(globalPointEdges, globalPointPoints);
891 
892 
893  // 3. Now all points have
894  // - all the connected points with original transform
895  // - all the connected global edges
896 
897  // Now all we need to do is go through all the edges and check
898  // both endpoints. If there is a edge between the two which is
899  // produced by transforming both points in the same way it is a shared
900  // edge.
901 
902  // Collect strings of connected edges.
903  List<labelPairList> allEdgeConnectivity(edges.size());
904 
905  forAll(edges, edgeI)
906  {
907  const edge& e = edges[edgeI];
908  const labelList& pEdges0 = globalPointEdges[e[0]];
909  const labelPairList& pPoints0 = globalPointPoints[e[0]];
910  const labelList& pEdges1 = globalPointEdges[e[1]];
911  const labelPairList& pPoints1 = globalPointPoints[e[1]];
912 
913  // Most edges will be size 2
914  DynamicList<labelPair> eEdges(2);
915  // Append myself.
916  eEdges.append
917  (
918  transforms.encode
919  (
921  edgeI,
922  transforms.nullTransformIndex()
923  )
924  );
925 
926  forAll(pEdges0, i)
927  {
928  forAll(pEdges1, j)
929  {
930  if
931  (
932  pEdges0[i] == pEdges1[j]
933  && pEdges0[i] != globalEdgeNumbers.toGlobal(edgeI)
934  )
935  {
936  // Found a shared edge. Now check if the endpoints
937  // go through the same transformation.
938  // Local: e[0] remote:pPoints1[j]
939  // Local: e[1] remote:pPoints0[i]
940 
941 
942  // Find difference in transforms to go from point on remote
943  // edge (pPoints1[j]) to this point.
944 
945  label transform0 = findTransform
946  (
947  allPointConnectivity[e[0]],
948  pPoints1[j],
949  e[0]
950  );
951  label transform1 = findTransform
952  (
953  allPointConnectivity[e[1]],
954  pPoints0[i],
955  e[1]
956  );
957 
958  if (transform0 == transform1)
959  {
960  label proci = globalEdgeNumbers.whichProcID(pEdges0[i]);
961  eEdges.append
962  (
963  transforms.encode
964  (
965  proci,
966  globalEdgeNumbers.toLocal(proci, pEdges0[i]),
967  transform0
968  )
969  );
970  }
971  }
972  }
973  }
974 
975  allEdgeConnectivity[edgeI].transfer(eEdges);
976  sort
977  (
978  allEdgeConnectivity[edgeI],
980  );
981  }
982 
983  // We now have - in allEdgeConnectivity - a list of edges which are shared
984  // between multiple processors. Filter into non-transformed and transformed
985  // connections.
986 
987  globalEdgeSlavesPtr_.reset(new labelListList(edges.size()));
988  labelListList& globalEdgeSlaves = globalEdgeSlavesPtr_();
989  List<labelPairList> transformedEdges(edges.size());
990  forAll(allEdgeConnectivity, edgeI)
991  {
992  const labelPairList& edgeInfo = allEdgeConnectivity[edgeI];
993  if (edgeInfo.size() >= 2)
994  {
995  const labelPair& masterInfo = edgeInfo[0];
996 
997  // Check if master edge (= first element (since sorted)) is me.
998  if
999  (
1000  (
1001  transforms.processor(masterInfo)
1002  == Pstream::myProcNo()
1003  )
1004  && (transforms.index(masterInfo) == edgeI)
1005  )
1006  {
1007  // Sort into transformed and untransformed
1008  labelList& eEdges = globalEdgeSlaves[edgeI];
1009  eEdges.setSize(edgeInfo.size()-1);
1010 
1011  labelPairList& trafoEEdges = transformedEdges[edgeI];
1012  trafoEEdges.setSize(edgeInfo.size()-1);
1013 
1014  label nonTransformI = 0;
1015  label transformI = 0;
1016 
1017  for (label i = 1; i < edgeInfo.size(); i++)
1018  {
1019  const labelPair& info = edgeInfo[i];
1020  label proci = transforms.processor(info);
1021  label index = transforms.index(info);
1022  label transform = transforms.transformIndex
1023  (
1024  info
1025  );
1026 
1027  if (transform == transforms.nullTransformIndex())
1028  {
1029  eEdges[nonTransformI++] = globalEdgeNumbers.toGlobal
1030  (
1031  proci,
1032  index
1033  );
1034  }
1035  else
1036  {
1037  trafoEEdges[transformI++] = info;
1038  }
1039  }
1040 
1041  eEdges.setSize(nonTransformI);
1042  trafoEEdges.setSize(transformI);
1043  }
1044  }
1045  }
1046 
1047 
1048  // Construct map
1049  globalEdgeTransformedSlavesPtr_.reset(new labelListList());
1050 
1051  List<Map<label>> compactMap(Pstream::nProcs());
1052  globalEdgeSlavesMapPtr_.reset
1053  (
1054  new mapDistribute
1055  (
1056  globalEdgeNumbers,
1057  globalEdgeSlaves,
1058 
1059  transforms,
1060  transformedEdges,
1061  globalEdgeTransformedSlavesPtr_(),
1062 
1063  compactMap
1064  )
1065  );
1066 
1067 
1068  if (debug)
1069  {
1070  Pout<< "globalMeshData::calcGlobalEdgeSlaves() :"
1071  << " coupled edges:" << edges.size()
1072  << " additional coupled edges:"
1073  << globalEdgeSlavesMapPtr_().constructSize() - edges.size()
1074  << endl;
1075  }
1076 }
1077 
1078 
1079 void Foam::globalMeshData::calcGlobalEdgeOrientation() const
1080 {
1081  if (debug)
1082  {
1083  Pout<< "globalMeshData::calcGlobalEdgeOrientation() :"
1084  << " calculating edge orientation w.r.t. master edge." << endl;
1085  }
1086 
1087  const globalIndex& globalPoints = globalPointNumbering();
1088 
1089  // 1. Determine master point
1090  labelList masterPoint;
1091  {
1092  const mapDistribute& map = globalPointSlavesMap();
1093 
1094  masterPoint.setSize(map.constructSize());
1095  masterPoint = labelMax;
1096 
1097  for (label pointi = 0; pointi < coupledPatch().nPoints(); pointi++)
1098  {
1099  masterPoint[pointi] = globalPoints.toGlobal(pointi);
1100  }
1101  syncData
1102  (
1103  masterPoint,
1104  globalPointSlaves(),
1105  globalPointTransformedSlaves(),
1106  map,
1107  minEqOp<label>()
1108  );
1109  }
1110 
1111  // Now all points should know who is master by comparing their global
1112  // pointID with the masterPointID. We now can use this information
1113  // to find the orientation of the master edge.
1114 
1115  {
1116  const mapDistribute& map = globalEdgeSlavesMap();
1117  const labelListList& slaves = globalEdgeSlaves();
1118  const labelListList& transformedSlaves = globalEdgeTransformedSlaves();
1119 
1120  // Distribute orientation of master edge (in masterPoint numbering)
1121  labelPairList masterEdgeVerts(map.constructSize());
1122  masterEdgeVerts = labelPair(labelMax, labelMax);
1123 
1124  for (label edgeI = 0; edgeI < coupledPatch().nEdges(); edgeI++)
1125  {
1126  if
1127  (
1128  (
1129  slaves[edgeI].size()
1130  + transformedSlaves[edgeI].size()
1131  )
1132  > 0
1133  )
1134  {
1135  // I am master. Fill in my masterPoint equivalent.
1136 
1137  const edge& e = coupledPatch().edges()[edgeI];
1138  masterEdgeVerts[edgeI] = labelPair
1139  (
1140  masterPoint[e[0]],
1141  masterPoint[e[1]]
1142  );
1143  }
1144  }
1145  syncData
1146  (
1147  masterEdgeVerts,
1148  slaves,
1149  transformedSlaves,
1150  map,
1151  minEqOp<labelPair>()
1152  );
1153 
1154  // Now check my edges on how they relate to the master's edgeVerts
1155  globalEdgeOrientationPtr_.reset
1156  (
1157  new bitSet(coupledPatch().nEdges())
1158  );
1159  bitSet& globalEdgeOrientation = globalEdgeOrientationPtr_();
1160 
1161  forAll(coupledPatch().edges(), edgeI)
1162  {
1163  // Test that edge is not single edge on cyclic baffle
1164  if (masterEdgeVerts[edgeI] != labelPair(labelMax, labelMax))
1165  {
1166  const edge& e = coupledPatch().edges()[edgeI];
1167  const labelPair masterE
1168  (
1169  masterPoint[e[0]],
1170  masterPoint[e[1]]
1171  );
1172 
1173  const int stat = labelPair::compare
1174  (
1175  masterE,
1176  masterEdgeVerts[edgeI]
1177  );
1178  if (stat == 0)
1179  {
1181  << "problem : my edge:" << e
1182  << " in master points:" << masterE
1183  << " v.s. masterEdgeVerts:" << masterEdgeVerts[edgeI]
1184  << exit(FatalError);
1185  }
1186  else
1187  {
1188  globalEdgeOrientation.set(edgeI, (stat == 1));
1189  }
1190  }
1191  else
1192  {
1193  globalEdgeOrientation.set(edgeI, true);
1194  }
1195  }
1196  }
1197 
1198  if (debug)
1199  {
1200  Pout<< "globalMeshData::calcGlobalEdgeOrientation() :"
1201  << " finished calculating edge orientation."
1202  << endl;
1203  }
1204 }
1205 
1206 
1207 void Foam::globalMeshData::calcPointBoundaryFaces
1208 (
1209  labelListList& pointBoundaryFaces
1210 ) const
1211 {
1212  const polyBoundaryMesh& bMesh = mesh_.boundaryMesh();
1213  const Map<label>& meshPointMap = coupledPatch().meshPointMap();
1214 
1215  // 1. Count
1216 
1217  labelList nPointFaces(coupledPatch().nPoints(), Zero);
1218 
1219  for (const polyPatch& pp : bMesh)
1220  {
1221  if (!pp.coupled())
1222  {
1223  for (const face& f : pp)
1224  {
1225  forAll(f, fp)
1226  {
1227  const auto iter = meshPointMap.cfind(f[fp]);
1228  if (iter.found())
1229  {
1230  nPointFaces[iter.val()]++;
1231  }
1232  }
1233  }
1234  }
1235  }
1236 
1237 
1238  // 2. Size
1239 
1240  pointBoundaryFaces.setSize(coupledPatch().nPoints());
1241  forAll(nPointFaces, pointi)
1242  {
1243  pointBoundaryFaces[pointi].setSize(nPointFaces[pointi]);
1244  }
1245  nPointFaces = 0;
1246 
1247 
1248  // 3. Fill
1249 
1250  forAll(bMesh, patchi)
1251  {
1252  const polyPatch& pp = bMesh[patchi];
1253 
1254  if (!pp.coupled())
1255  {
1256  forAll(pp, i)
1257  {
1258  const face& f = pp[i];
1259  forAll(f, fp)
1260  {
1261  const auto iter = meshPointMap.cfind(f[fp]);
1262 
1263  if (iter.found())
1264  {
1265  label bFacei =
1266  pp.start() + i - mesh_.nInternalFaces();
1267  pointBoundaryFaces[iter()][nPointFaces[iter()]++] =
1268  bFacei;
1269  }
1270  }
1271  }
1272  }
1273  }
1274 }
1275 
1276 
1277 void Foam::globalMeshData::calcGlobalPointBoundaryFaces() const
1278 {
1279  if (debug)
1280  {
1281  Pout<< "globalMeshData::calcGlobalPointBoundaryFaces() :"
1282  << " calculating coupled point to boundary face addressing."
1283  << endl;
1284  }
1285 
1286  // Construct local point to (uncoupled)boundaryfaces.
1287  labelListList pointBoundaryFaces;
1288  calcPointBoundaryFaces(pointBoundaryFaces);
1289 
1290 
1291  // Global indices for boundary faces
1292  globalBoundaryFaceNumberingPtr_.reset
1293  (
1294  new globalIndex(mesh_.nBoundaryFaces())
1295  );
1296  globalIndex& globalIndices = globalBoundaryFaceNumberingPtr_();
1297 
1298 
1299  // Convert local boundary faces to global numbering
1300  globalPointBoundaryFacesPtr_.reset
1301  (
1302  new labelListList(globalPointSlavesMap().constructSize())
1303  );
1304  labelListList& globalPointBoundaryFaces = globalPointBoundaryFacesPtr_();
1305 
1306  forAll(pointBoundaryFaces, pointi)
1307  {
1308  const labelList& bFaces = pointBoundaryFaces[pointi];
1309  labelList& globalFaces = globalPointBoundaryFaces[pointi];
1310  globalFaces.setSize(bFaces.size());
1311  forAll(bFaces, i)
1312  {
1313  globalFaces[i] = globalIndices.toGlobal(bFaces[i]);
1314  }
1315  }
1316 
1317 
1318  // Pull slave pointBoundaryFaces to master
1319  globalPointSlavesMap().distribute
1320  (
1321  globalPointBoundaryFaces,
1322  true // put data on transformed points into correct slots
1323  );
1324 
1325 
1326  // Merge slave labels into master globalPointBoundaryFaces.
1327  // Split into untransformed and transformed values.
1328  const labelListList& pointSlaves = globalPointSlaves();
1329  const labelListList& pointTransformSlaves =
1330  globalPointTransformedSlaves();
1331  const globalIndexAndTransform& transforms = globalTransforms();
1332 
1333 
1334  // Any faces coming in through transformation
1335  List<labelPairList> transformedFaces(pointSlaves.size());
1336 
1337 
1338  forAll(pointSlaves, pointi)
1339  {
1340  const labelList& slaves = pointSlaves[pointi];
1341  const labelList& transformedSlaves = pointTransformSlaves[pointi];
1342 
1343  if (slaves.size() > 0)
1344  {
1345  labelList& myBFaces = globalPointBoundaryFaces[pointi];
1346  label sz = myBFaces.size();
1347 
1348  // Count
1349  label n = 0;
1350  forAll(slaves, i)
1351  {
1352  n += globalPointBoundaryFaces[slaves[i]].size();
1353  }
1354  // Fill
1355  myBFaces.setSize(sz+n);
1356  n = sz;
1357  forAll(slaves, i)
1358  {
1359  const labelList& slaveBFaces =
1360  globalPointBoundaryFaces[slaves[i]];
1361 
1362  // Add all slaveBFaces. Note that need to check for
1363  // uniqueness only in case of cyclics.
1364 
1365  for (const label slave : slaveBFaces)
1366  {
1367  if (!SubList<label>(myBFaces, sz).found(slave))
1368  {
1369  myBFaces[n++] = slave;
1370  }
1371  }
1372  }
1373  myBFaces.setSize(n);
1374  }
1375 
1376 
1377  if (transformedSlaves.size() > 0)
1378  {
1379  const labelList& untrafoFaces = globalPointBoundaryFaces[pointi];
1380 
1381  labelPairList& myBFaces = transformedFaces[pointi];
1382  label sz = myBFaces.size();
1383 
1384  // Count
1385  label n = 0;
1386  forAll(transformedSlaves, i)
1387  {
1388  n += globalPointBoundaryFaces[transformedSlaves[i]].size();
1389  }
1390  // Fill
1391  myBFaces.setSize(sz+n);
1392  n = sz;
1393  forAll(transformedSlaves, i)
1394  {
1395  label transformI = globalPointSlavesMap().whichTransform
1396  (
1397  transformedSlaves[i]
1398  );
1399 
1400  const labelList& slaveBFaces =
1401  globalPointBoundaryFaces[transformedSlaves[i]];
1402 
1403  for (const label slave : slaveBFaces)
1404  {
1405  // Check that same face not already present untransformed
1406  if (!untrafoFaces.found(slave))
1407  {
1408  label proci = globalIndices.whichProcID(slave);
1409  label facei = globalIndices.toLocal(proci, slave);
1410 
1411  myBFaces[n++] = transforms.encode
1412  (
1413  proci,
1414  facei,
1415  transformI
1416  );
1417  }
1418  }
1419  }
1420  myBFaces.setSize(n);
1421  }
1422 
1423 
1424  if (slaves.size() + transformedSlaves.size() == 0)
1425  {
1426  globalPointBoundaryFaces[pointi].clear();
1427  }
1428  }
1429 
1430  // Construct a map to get the face data directly
1431  List<Map<label>> compactMap(Pstream::nProcs());
1432 
1433  globalPointTransformedBoundaryFacesPtr_.reset
1434  (
1435  new labelListList(transformedFaces.size())
1436  );
1437 
1438  globalPointBoundaryFacesMapPtr_.reset
1439  (
1440  new mapDistribute
1441  (
1442  globalIndices,
1443  globalPointBoundaryFaces,
1444 
1445  transforms,
1446  transformedFaces,
1447  globalPointTransformedBoundaryFacesPtr_(),
1448 
1449  compactMap
1450  )
1451  );
1452  globalPointBoundaryFaces.setSize(coupledPatch().nPoints());
1453  globalPointTransformedBoundaryFacesPtr_().setSize(coupledPatch().nPoints());
1454 
1455  if (debug)
1456  {
1457  Pout<< "globalMeshData::calcGlobalPointBoundaryFaces() :"
1458  << " coupled points:" << coupledPatch().nPoints()
1459  << " local boundary faces:" << globalIndices.localSize()
1460  << " additional coupled faces:"
1461  << globalPointBoundaryFacesMapPtr_().constructSize()
1462  - globalIndices.localSize()
1463  << endl;
1464  }
1465 }
1466 
1467 
1468 void Foam::globalMeshData::calcGlobalPointBoundaryCells() const
1469 {
1470  if (debug)
1471  {
1472  Pout<< "globalMeshData::calcGlobalPointBoundaryCells() :"
1473  << " calculating coupled point to boundary cell addressing."
1474  << endl;
1475  }
1476 
1477  // Create map of boundary cells and point-cell addressing
1478  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1479 
1480  label bCelli = 0;
1481  Map<label> meshCellMap(4*coupledPatch().nPoints());
1482  DynamicList<label> cellMap(meshCellMap.size());
1483 
1484  // Create addressing for point to boundary cells (local)
1485  labelListList pointBoundaryCells(coupledPatch().nPoints());
1486 
1487  forAll(coupledPatch().meshPoints(), pointi)
1488  {
1489  label meshPointi = coupledPatch().meshPoints()[pointi];
1490  const labelList& pCells = mesh_.pointCells(meshPointi);
1491 
1492  labelList& bCells = pointBoundaryCells[pointi];
1493  bCells.setSize(pCells.size());
1494 
1495  forAll(pCells, i)
1496  {
1497  const label celli = pCells[i];
1498  const auto fnd = meshCellMap.cfind(celli);
1499 
1500  if (fnd.found())
1501  {
1502  bCells[i] = fnd();
1503  }
1504  else
1505  {
1506  meshCellMap.insert(celli, bCelli);
1507  cellMap.append(celli);
1508  bCells[i] = bCelli;
1509  bCelli++;
1510  }
1511  }
1512  }
1513 
1514 
1515  boundaryCellsPtr_.reset(new labelList(std::move(cellMap)));
1516  labelList& boundaryCells = boundaryCellsPtr_();
1517 
1518 
1519  // Convert point-cells to global (boundary)cell numbers
1520  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1521 
1522  globalBoundaryCellNumberingPtr_.reset
1523  (
1524  new globalIndex(boundaryCells.size())
1525  );
1526  globalIndex& globalIndices = globalBoundaryCellNumberingPtr_();
1527 
1528 
1529  globalPointBoundaryCellsPtr_.reset
1530  (
1531  new labelListList(globalPointSlavesMap().constructSize())
1532  );
1533  labelListList& globalPointBoundaryCells = globalPointBoundaryCellsPtr_();
1534 
1535  forAll(pointBoundaryCells, pointi)
1536  {
1537  const labelList& pCells = pointBoundaryCells[pointi];
1538  labelList& globalCells = globalPointBoundaryCells[pointi];
1539  globalCells.setSize(pCells.size());
1540  forAll(pCells, i)
1541  {
1542  globalCells[i] = globalIndices.toGlobal(pCells[i]);
1543  }
1544  }
1545 
1546 
1547  // Pull slave pointBoundaryCells to master
1548  globalPointSlavesMap().distribute
1549  (
1550  globalPointBoundaryCells,
1551  true // put data on transformed points into correct slots
1552  );
1553 
1554 
1555  // Merge slave labels into master globalPointBoundaryCells
1556  const labelListList& pointSlaves = globalPointSlaves();
1557  const labelListList& pointTransformSlaves =
1558  globalPointTransformedSlaves();
1559  const globalIndexAndTransform& transforms = globalTransforms();
1560 
1561  List<labelPairList> transformedCells(pointSlaves.size());
1562 
1563 
1564  forAll(pointSlaves, pointi)
1565  {
1566  const labelList& slaves = pointSlaves[pointi];
1567  const labelList& transformedSlaves = pointTransformSlaves[pointi];
1568 
1569  if (slaves.size() > 0)
1570  {
1571  labelList& myBCells = globalPointBoundaryCells[pointi];
1572  label sz = myBCells.size();
1573 
1574  // Count
1575  label n = 0;
1576  forAll(slaves, i)
1577  {
1578  n += globalPointBoundaryCells[slaves[i]].size();
1579  }
1580  // Fill
1581  myBCells.setSize(sz+n);
1582  n = sz;
1583  forAll(slaves, i)
1584  {
1585  const labelList& slaveBCells =
1586  globalPointBoundaryCells[slaves[i]];
1587 
1588  // Add all slaveBCells. Note that need to check for
1589  // uniqueness only in case of cyclics.
1590 
1591  for (const label slave : slaveBCells)
1592  {
1593  if (!SubList<label>(myBCells, sz).found(slave))
1594  {
1595  myBCells[n++] = slave;
1596  }
1597  }
1598  }
1599  myBCells.setSize(n);
1600  }
1601 
1602 
1603  if (transformedSlaves.size() > 0)
1604  {
1605  const labelList& untrafoCells = globalPointBoundaryCells[pointi];
1606 
1607  labelPairList& myBCells = transformedCells[pointi];
1608  label sz = myBCells.size();
1609 
1610  // Count
1611  label n = 0;
1612  forAll(transformedSlaves, i)
1613  {
1614  n += globalPointBoundaryCells[transformedSlaves[i]].size();
1615  }
1616  // Fill
1617  myBCells.setSize(sz+n);
1618  n = sz;
1619  forAll(transformedSlaves, i)
1620  {
1621  label transformI = globalPointSlavesMap().whichTransform
1622  (
1623  transformedSlaves[i]
1624  );
1625 
1626  const labelList& slaveBCells =
1627  globalPointBoundaryCells[transformedSlaves[i]];
1628 
1629  for (const label slave : slaveBCells)
1630  {
1631  // Check that same cell not already present untransformed
1632  if (!untrafoCells.found(slave))
1633  {
1634  label proci = globalIndices.whichProcID(slave);
1635  label celli = globalIndices.toLocal(proci, slave);
1636  myBCells[n++] = transforms.encode
1637  (
1638  proci,
1639  celli,
1640  transformI
1641  );
1642  }
1643  }
1644  }
1645  myBCells.setSize(n);
1646  }
1647 
1648  if (slaves.size() + transformedSlaves.size() == 0)
1649  {
1650  globalPointBoundaryCells[pointi].clear();
1651  }
1652  }
1653 
1654  // Construct a map to get the cell data directly
1655  List<Map<label>> compactMap(Pstream::nProcs());
1656 
1657  globalPointTransformedBoundaryCellsPtr_.reset
1658  (
1659  new labelListList(transformedCells.size())
1660  );
1661 
1662  globalPointBoundaryCellsMapPtr_.reset
1663  (
1664  new mapDistribute
1665  (
1666  globalIndices,
1667  globalPointBoundaryCells,
1668 
1669  transforms,
1670  transformedCells,
1671  globalPointTransformedBoundaryCellsPtr_(),
1672 
1673  compactMap
1674  )
1675  );
1676  globalPointBoundaryCells.setSize(coupledPatch().nPoints());
1677  globalPointTransformedBoundaryCellsPtr_().setSize(coupledPatch().nPoints());
1678 
1679  if (debug)
1680  {
1681  Pout<< "globalMeshData::calcGlobalPointBoundaryCells() :"
1682  << " coupled points:" << coupledPatch().nPoints()
1683  << " local boundary cells:" << globalIndices.localSize()
1684  << " additional coupled cells:"
1685  << globalPointBoundaryCellsMapPtr_().constructSize()
1686  - globalIndices.localSize()
1687  << endl;
1688  }
1689 }
1690 
1691 
1692 void Foam::globalMeshData::calcGlobalCoPointSlaves() const
1693 {
1694  if (debug)
1695  {
1696  Pout<< "globalMeshData::calcGlobalCoPointSlaves() :"
1697  << " calculating coupled master to collocated"
1698  << " slave point addressing." << endl;
1699  }
1700 
1701  // Calculate connected points for master points.
1702  globalPoints globalData(mesh_, coupledPatch(), true, false);
1703 
1704  globalCoPointSlavesPtr_.reset
1705  (
1706  new labelListList
1707  (
1708  std::move(globalData.pointPoints())
1709  )
1710  );
1711  globalCoPointSlavesMapPtr_.reset
1712  (
1713  new mapDistribute
1714  (
1715  std::move(globalData.map())
1716  )
1717  );
1718 
1719  if (debug)
1720  {
1721  Pout<< "globalMeshData::calcGlobalCoPointSlaves() :"
1722  << " finished calculating coupled master to collocated"
1723  << " slave point addressing." << endl;
1724  }
1725 }
1726 
1727 
1728 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
1729 
1730 Foam::globalMeshData::globalMeshData(const polyMesh& mesh)
1731 :
1732  mesh_(mesh),
1733  nTotalPoints_(-1),
1734  nTotalFaces_(-1),
1735  nTotalCells_(-1),
1736  processorTopology_
1737  (
1738  processorTopology::New<processorPolyPatch>
1739  (
1740  mesh.boundaryMesh(),
1741  UPstream::worldComm
1742  )
1743  ),
1744  processorPatches_(),
1745  processorPatchIndices_(),
1746  processorPatchNeighbours_(),
1747  nGlobalPoints_(-1),
1748  sharedPointLabelsPtr_(nullptr),
1749  sharedPointAddrPtr_(nullptr),
1750  sharedPointGlobalLabelsPtr_(nullptr),
1751  nGlobalEdges_(-1),
1752  sharedEdgeLabelsPtr_(nullptr),
1753  sharedEdgeAddrPtr_(nullptr)
1754 {
1756 }
1757 
1758 
1759 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
1760 
1761 // A non-default destructor since we had incomplete types in the header
1763 {}
1764 
1765 
1767 {
1768  // Point
1769  nGlobalPoints_ = -1;
1770  sharedPointLabelsPtr_.clear();
1771  sharedPointAddrPtr_.clear();
1772  sharedPointGlobalLabelsPtr_.clear();
1773 
1774  // Edge
1775  nGlobalEdges_ = -1;
1776  sharedEdgeLabelsPtr_.clear();
1777  sharedEdgeAddrPtr_.clear();
1778 
1779  // Coupled patch
1780  coupledPatchPtr_.clear();
1781  coupledPatchMeshEdgesPtr_.clear();
1782  coupledPatchMeshEdgeMapPtr_.clear();
1783  globalTransformsPtr_.clear();
1784 
1785  // Point
1786  globalPointNumberingPtr_.clear();
1787  globalPointSlavesPtr_.clear();
1788  globalPointTransformedSlavesPtr_.clear();
1789  globalPointSlavesMapPtr_.clear();
1790 
1791  // Edge
1792  globalEdgeNumberingPtr_.clear();
1793  globalEdgeSlavesPtr_.clear();
1794  globalEdgeTransformedSlavesPtr_.clear();
1795  globalEdgeOrientationPtr_.clear();
1796  globalEdgeSlavesMapPtr_.clear();
1797 
1798  // Face
1799  globalBoundaryFaceNumberingPtr_.clear();
1800  globalPointBoundaryFacesPtr_.clear();
1801  globalPointTransformedBoundaryFacesPtr_.clear();
1802  globalPointBoundaryFacesMapPtr_.clear();
1803 
1804  // Cell
1805  boundaryCellsPtr_.clear();
1806  globalBoundaryCellNumberingPtr_.clear();
1807  globalPointBoundaryCellsPtr_.clear();
1808  globalPointTransformedBoundaryCellsPtr_.clear();
1809  globalPointBoundaryCellsMapPtr_.clear();
1810 
1811  // Other: collocated points
1812  globalCoPointSlavesPtr_.clear();
1813  globalCoPointSlavesMapPtr_.clear();
1814 }
1815 
1816 
1817 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
1818 
1820 {
1821  if (!sharedPointGlobalLabelsPtr_)
1822  {
1823  sharedPointGlobalLabelsPtr_.reset
1824  (
1825  new labelList(sharedPointLabels().size())
1826  );
1827  labelList& sharedPointGlobalLabels = sharedPointGlobalLabelsPtr_();
1828 
1829  IOobject addrHeader
1830  (
1831  "pointProcAddressing",
1832  mesh_.facesInstance()/mesh_.meshSubDir,
1833  mesh_,
1835  );
1836 
1837  if (addrHeader.typeHeaderOk<labelIOList>(true))
1838  {
1839  // There is a pointProcAddressing file so use it to get labels
1840  // on the original mesh
1841  Pout<< "globalMeshData::sharedPointGlobalLabels : "
1842  << "Reading pointProcAddressing" << endl;
1843 
1844  labelIOList pointProcAddressing(addrHeader);
1845 
1846  const labelList& pointLabels = sharedPointLabels();
1847 
1848  forAll(pointLabels, i)
1849  {
1850  // Get my mesh point
1851  label pointi = pointLabels[i];
1852 
1853  // Map to mesh point of original mesh
1854  sharedPointGlobalLabels[i] = pointProcAddressing[pointi];
1855  }
1856  }
1857  else
1858  {
1859  Pout<< "globalMeshData::sharedPointGlobalLabels :"
1860  << " Setting pointProcAddressing to -1" << endl;
1861 
1862  sharedPointGlobalLabels = -1;
1863  }
1864  }
1865 
1866  return *sharedPointGlobalLabelsPtr_;
1867 }
1868 
1869 
1871 {
1872  // Get all processors to send their shared points to master.
1873  // (not very efficient)
1874 
1875  pointField sharedPoints(nGlobalPoints());
1876  const labelList& pointAddr = sharedPointAddr();
1877  const labelList& pointLabels = sharedPointLabels();
1878 
1879  if (Pstream::master())
1880  {
1881  // Master:
1882  // insert my own data first
1883  forAll(pointLabels, i)
1884  {
1885  label sharedPointi = pointAddr[i];
1886 
1887  sharedPoints[sharedPointi] = mesh_.points()[pointLabels[i]];
1888  }
1889 
1890  // Receive data and insert
1891  for (const int proci : Pstream::subProcs())
1892  {
1893  IPstream fromProc(Pstream::commsTypes::blocking, proci);
1894 
1895  labelList nbrSharedPointAddr;
1896  pointField nbrSharedPoints;
1897  fromProc >> nbrSharedPointAddr >> nbrSharedPoints;
1898 
1899  forAll(nbrSharedPointAddr, i)
1900  {
1901  label sharedPointi = nbrSharedPointAddr[i];
1902 
1903  sharedPoints[sharedPointi] = nbrSharedPoints[i];
1904  }
1905  }
1906  }
1907  else
1908  {
1909  if (Pstream::parRun())
1910  {
1911  // Send address and points
1912  OPstream toMaster
1913  (
1916  );
1917  toMaster
1918  << pointAddr
1919  << pointField(mesh_.points(), pointLabels);
1920  }
1921  }
1922 
1923  // Broadcast: sharedPoints to all
1924  Pstream::broadcast(sharedPoints); // == worldComm
1925 
1926 
1927  return sharedPoints;
1928 }
1929 
1930 
1932 {
1933  // Get coords of my shared points
1934  pointField sharedPoints(mesh_.points(), sharedPointLabels());
1935 
1936  // Append from all processors, globally consistent
1938 
1939  // Merge tolerance
1940  scalar tolDim = matchTol_ * mesh_.bounds().mag();
1941 
1942  labelList pointMap;
1944  (
1945  sharedPoints, // coordinates to merge
1946  tolDim, // tolerance
1947  false, // verbosity
1948  pointMap
1949  );
1950 
1951  return sharedPoints;
1952 }
1953 
1954 
1955 Foam::label Foam::globalMeshData::nGlobalPoints() const
1956 {
1957  if (nGlobalPoints_ == -1)
1958  {
1959  calcSharedPoints();
1960  }
1961  return nGlobalPoints_;
1962 }
1963 
1964 
1966 {
1967  if (!sharedPointLabelsPtr_)
1968  {
1969  calcSharedPoints();
1970  }
1971  return *sharedPointLabelsPtr_;
1972 }
1973 
1974 
1976 {
1977  if (!sharedPointAddrPtr_)
1978  {
1979  calcSharedPoints();
1980  }
1981  return *sharedPointAddrPtr_;
1982 }
1983 
1984 
1985 Foam::label Foam::globalMeshData::nGlobalEdges() const
1986 {
1987  if (nGlobalEdges_ == -1)
1988  {
1989  calcSharedEdges();
1990  }
1991  return nGlobalEdges_;
1992 }
1993 
1994 
1996 {
1997  if (!sharedEdgeLabelsPtr_)
1998  {
1999  calcSharedEdges();
2000  }
2001  return *sharedEdgeLabelsPtr_;
2002 }
2003 
2004 
2006 {
2007  if (!sharedEdgeAddrPtr_)
2008  {
2009  calcSharedEdges();
2010  }
2011  return *sharedEdgeAddrPtr_;
2012 }
2013 
2014 
2016 {
2017  if (!coupledPatchPtr_)
2018  {
2019  const polyBoundaryMesh& bMesh = mesh_.boundaryMesh();
2020 
2021  label nCoupled = 0;
2022 
2023  forAll(bMesh, patchi)
2024  {
2025  const polyPatch& pp = bMesh[patchi];
2026 
2027  if (pp.coupled())
2028  {
2029  nCoupled += pp.size();
2030  }
2031  }
2032  labelList coupledFaces(nCoupled);
2033  nCoupled = 0;
2034 
2035  forAll(bMesh, patchi)
2036  {
2037  const polyPatch& pp = bMesh[patchi];
2038 
2039  if (pp.coupled())
2040  {
2041  label facei = pp.start();
2042 
2043  forAll(pp, i)
2044  {
2045  coupledFaces[nCoupled++] = facei++;
2046  }
2047  }
2048  }
2049 
2050  coupledPatchPtr_.reset
2051  (
2053  (
2054  IndirectList<face>
2055  (
2056  mesh_.faces(),
2057  coupledFaces
2058  ),
2059  mesh_.points()
2060  )
2061  );
2062 
2063  if (debug)
2064  {
2065  Pout<< "globalMeshData::coupledPatch() :"
2066  << " constructed coupled faces patch:"
2067  << " faces:" << coupledPatchPtr_().size()
2068  << " points:" << coupledPatchPtr_().nPoints()
2069  << endl;
2070  }
2071  }
2072  return *coupledPatchPtr_;
2073 }
2074 
2075 
2077 {
2078  if (!coupledPatchMeshEdgesPtr_)
2079  {
2080  coupledPatchMeshEdgesPtr_.reset
2081  (
2082  new labelList
2083  (
2084  coupledPatch().meshEdges
2085  (
2086  mesh_.edges(),
2087  mesh_.pointEdges()
2088  )
2089  )
2090  );
2091  }
2092  return *coupledPatchMeshEdgesPtr_;
2093 }
2094 
2095 
2097 const
2098 {
2099  if (!coupledPatchMeshEdgeMapPtr_)
2100  {
2101  const labelList& me = coupledPatchMeshEdges();
2102 
2103  coupledPatchMeshEdgeMapPtr_.reset(new Map<label>(2*me.size()));
2104  Map<label>& em = coupledPatchMeshEdgeMapPtr_();
2105 
2106  forAll(me, i)
2107  {
2108  em.insert(me[i], i);
2109  }
2110  }
2111  return *coupledPatchMeshEdgeMapPtr_;
2112 }
2113 
2114 
2116 {
2117  if (!globalPointNumberingPtr_)
2118  {
2119  globalPointNumberingPtr_.reset
2120  (
2121  new globalIndex(coupledPatch().nPoints())
2122  );
2123  }
2124  return *globalPointNumberingPtr_;
2125 }
2126 
2127 
2130 {
2131  if (!globalTransformsPtr_)
2132  {
2133  globalTransformsPtr_.reset(new globalIndexAndTransform(mesh_));
2134  }
2135  return *globalTransformsPtr_;
2136 }
2137 
2138 
2140 {
2141  if (!globalPointSlavesPtr_)
2142  {
2143  calcGlobalPointSlaves();
2144  }
2145  return *globalPointSlavesPtr_;
2146 }
2147 
2148 
2150 const
2151 {
2152  if (!globalPointTransformedSlavesPtr_)
2153  {
2154  calcGlobalPointSlaves();
2155  }
2156  return *globalPointTransformedSlavesPtr_;
2157 }
2158 
2159 
2161 {
2162  if (!globalPointSlavesMapPtr_)
2163  {
2164  calcGlobalPointSlaves();
2165  }
2166  return *globalPointSlavesMapPtr_;
2167 }
2168 
2169 
2171 {
2172  if (!globalEdgeNumberingPtr_)
2173  {
2174  globalEdgeNumberingPtr_.reset
2175  (
2176  new globalIndex(coupledPatch().nEdges())
2177  );
2178  }
2179  return *globalEdgeNumberingPtr_;
2180 }
2181 
2182 
2184 {
2185  if (!globalEdgeSlavesPtr_)
2186  {
2187  calcGlobalEdgeSlaves();
2188  }
2189  return *globalEdgeSlavesPtr_;
2190 }
2191 
2192 
2194 const
2195 {
2196  if (!globalEdgeTransformedSlavesPtr_)
2197  {
2198  calcGlobalEdgeSlaves();
2199  }
2200  return *globalEdgeTransformedSlavesPtr_;
2201 }
2202 
2203 
2205 {
2206  if (!globalEdgeOrientationPtr_)
2207  {
2208  calcGlobalEdgeOrientation();
2209  }
2210  return *globalEdgeOrientationPtr_;
2211 }
2212 
2213 
2215 {
2216  if (!globalEdgeSlavesMapPtr_)
2217  {
2218  calcGlobalEdgeSlaves();
2219  }
2220  return *globalEdgeSlavesMapPtr_;
2221 }
2222 
2223 
2225 const
2226 {
2227  if (!globalBoundaryFaceNumberingPtr_)
2228  {
2229  calcGlobalPointBoundaryFaces();
2230  }
2231  return *globalBoundaryFaceNumberingPtr_;
2232 }
2233 
2234 
2236 const
2237 {
2238  if (!globalPointBoundaryFacesPtr_)
2239  {
2240  calcGlobalPointBoundaryFaces();
2241  }
2242  return *globalPointBoundaryFacesPtr_;
2243 }
2244 
2245 
2246 const Foam::labelListList&
2248 {
2249  if (!globalPointTransformedBoundaryFacesPtr_)
2250  {
2251  calcGlobalPointBoundaryFaces();
2252  }
2253  return *globalPointTransformedBoundaryFacesPtr_;
2254 }
2255 
2256 
2258 const
2259 {
2260  if (!globalPointBoundaryFacesMapPtr_)
2261  {
2262  calcGlobalPointBoundaryFaces();
2263  }
2264  return *globalPointBoundaryFacesMapPtr_;
2265 }
2266 
2267 
2269 {
2270  if (!boundaryCellsPtr_)
2271  {
2272  calcGlobalPointBoundaryCells();
2273  }
2274  return *boundaryCellsPtr_;
2275 }
2276 
2277 
2279 const
2280 {
2281  if (!globalBoundaryCellNumberingPtr_)
2282  {
2283  calcGlobalPointBoundaryCells();
2284  }
2285  return *globalBoundaryCellNumberingPtr_;
2286 }
2287 
2288 
2290 const
2291 {
2292  if (!globalPointBoundaryCellsPtr_)
2293  {
2294  calcGlobalPointBoundaryCells();
2295  }
2296  return *globalPointBoundaryCellsPtr_;
2297 }
2298 
2299 
2300 const Foam::labelListList&
2302 {
2303  if (!globalPointTransformedBoundaryCellsPtr_)
2304  {
2305  calcGlobalPointBoundaryCells();
2306  }
2307  return *globalPointTransformedBoundaryCellsPtr_;
2308 }
2309 
2310 
2312 const
2313 {
2314  if (!globalPointBoundaryCellsMapPtr_)
2315  {
2316  calcGlobalPointBoundaryCells();
2317  }
2318  return *globalPointBoundaryCellsMapPtr_;
2319 }
2320 
2321 
2323 {
2324  if (!globalCoPointSlavesPtr_)
2325  {
2326  calcGlobalCoPointSlaves();
2327  }
2328  return *globalCoPointSlavesPtr_;
2329 }
2330 
2331 
2333 {
2334  if (!globalCoPointSlavesMapPtr_)
2335  {
2336  calcGlobalCoPointSlaves();
2337  }
2338  return *globalCoPointSlavesMapPtr_;
2339 }
2340 
2341 
2343 (
2344  labelList& pointToGlobal,
2345  labelList& uniquePoints
2346 ) const
2347 {
2348  const indirectPrimitivePatch& cpp = coupledPatch();
2349  const globalIndex& globalCoupledPoints = globalPointNumbering();
2350  // Use collocated only
2351  const labelListList& pointSlaves = globalCoPointSlaves();
2352  const mapDistribute& pointSlavesMap = globalCoPointSlavesMap();
2353 
2354 
2355  // Points are either
2356  // - master with slaves
2357  // - slave with a master
2358  // - other (since e.g. non-collocated cyclics not connected)
2359 
2360  labelList masterGlobalPoint(cpp.nPoints(), -1);
2361  forAll(masterGlobalPoint, pointi)
2362  {
2363  const labelList& slavePoints = pointSlaves[pointi];
2364  if (slavePoints.size() > 0)
2365  {
2366  masterGlobalPoint[pointi] = globalCoupledPoints.toGlobal(pointi);
2367  }
2368  }
2369 
2370  // Sync by taking max
2371  syncData
2372  (
2373  masterGlobalPoint,
2374  pointSlaves,
2375  labelListList(0), // no transforms
2376  pointSlavesMap,
2377  maxEqOp<label>()
2378  );
2379 
2380 
2381  // 1. Count number of masters on my processor.
2382  label nMaster = 0;
2383  bitSet isMaster(mesh_.nPoints(), true);
2384  forAll(pointSlaves, pointi)
2385  {
2386  if (masterGlobalPoint[pointi] == -1)
2387  {
2388  // unconnected point (e.g. from separated cyclic)
2389  nMaster++;
2390  }
2391  else if
2392  (
2393  masterGlobalPoint[pointi]
2394  == globalCoupledPoints.toGlobal(pointi)
2395  )
2396  {
2397  // connected master
2398  nMaster++;
2399  }
2400  else
2401  {
2402  // connected slave point
2403  isMaster.unset(cpp.meshPoints()[pointi]);
2404  }
2405  }
2406 
2407  label myUniquePoints = mesh_.nPoints() - cpp.nPoints() + nMaster;
2408 
2409  //Pout<< "Points :" << nl
2410  // << " mesh : " << mesh_.nPoints() << nl
2411  // << " of which coupled : " << cpp.nPoints() << nl
2412  // << " of which master : " << nMaster << nl
2413  // << endl;
2414 
2415 
2416  // 2. Create global indexing for unique points.
2417  autoPtr<globalIndex> globalPointsPtr(new globalIndex(myUniquePoints));
2418 
2419 
2420  // 3. Assign global point numbers. Keep slaves unset.
2421  pointToGlobal.setSize(mesh_.nPoints());
2422  pointToGlobal = -1;
2423  uniquePoints.setSize(myUniquePoints);
2424  nMaster = 0;
2425 
2426  forAll(isMaster, meshPointi)
2427  {
2428  if (isMaster[meshPointi])
2429  {
2430  pointToGlobal[meshPointi] = globalPointsPtr().toGlobal(nMaster);
2431  uniquePoints[nMaster] = meshPointi;
2432  nMaster++;
2433  }
2434  }
2435 
2436 
2437  // 4. Push global index for coupled points to slaves.
2438  {
2439  labelList masterToGlobal(pointSlavesMap.constructSize(), -1);
2440 
2441  forAll(pointSlaves, pointi)
2442  {
2443  const labelList& slaves = pointSlaves[pointi];
2444 
2445  if (slaves.size() > 0)
2446  {
2447  // Duplicate master globalpoint into slave slots
2448  label meshPointi = cpp.meshPoints()[pointi];
2449  masterToGlobal[pointi] = pointToGlobal[meshPointi];
2450  forAll(slaves, i)
2451  {
2452  masterToGlobal[slaves[i]] = masterToGlobal[pointi];
2453  }
2454  }
2455  }
2456 
2457  // Send back
2458  pointSlavesMap.reverseDistribute(cpp.nPoints(), masterToGlobal);
2459 
2460  // On slave copy master index into overal map.
2461  forAll(pointSlaves, pointi)
2462  {
2463  label meshPointi = cpp.meshPoints()[pointi];
2464 
2465  if (!isMaster[meshPointi])
2466  {
2467  pointToGlobal[meshPointi] = masterToGlobal[pointi];
2468  }
2469  }
2470  }
2471 
2472  return globalPointsPtr;
2473 }
2474 
2475 
2477 (
2478  const labelUList& meshPoints,
2479  const Map<label>& /* unused: meshPointMap */,
2480  labelList& pointToGlobal,
2481  labelList& uniqueMeshPoints
2482 ) const
2483 {
2484  const indirectPrimitivePatch& cpp = coupledPatch();
2485  const labelListList& pointSlaves = globalCoPointSlaves();
2486  const mapDistribute& pointSlavesMap = globalCoPointSlavesMap();
2487 
2488 
2489  // The patch points come in two variants:
2490  // - not on a coupled patch so guaranteed unique
2491  // - on a coupled patch
2492  // If the point is on a coupled patch the problem is that the
2493  // master-slave structure (globalPointSlaves etc.) assigns one of the
2494  // coupled points to be the master but this master point is not
2495  // necessarily on the patch itself! (it might just be connected to the
2496  // patch point via coupled patches).
2497 
2498 
2499  // Determine mapping:
2500  // - from patch point to coupled point (or -1)
2501  // - from coupled point to global patch point
2502  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2503 
2504  const globalIndex globalPPoints(meshPoints.size());
2505 
2506  labelList patchToCoupled(meshPoints.size(), -1);
2507  label nCoupled = 0;
2508  labelList coupledToGlobalPatch(pointSlavesMap.constructSize(), -1);
2509 
2510  // Note: loop over patch since usually smaller
2511  forAll(meshPoints, patchPointi)
2512  {
2513  label meshPointi = meshPoints[patchPointi];
2514 
2515  const auto iter = cpp.meshPointMap().cfind(meshPointi);
2516 
2517  if (iter.found())
2518  {
2519  patchToCoupled[patchPointi] = iter();
2520  coupledToGlobalPatch[iter()] = globalPPoints.toGlobal(patchPointi);
2521  nCoupled++;
2522  }
2523  }
2524 
2525  //Pout<< "Patch:" << nl
2526  // << " points:" << meshPoints.size() << nl
2527  // << " of which on coupled patch:" << nCoupled << endl;
2528 
2529 
2530  // Determine master of connected points
2531  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2532  // Problem is that the coupled master might not be on the patch. So
2533  // work out the best patch-point master from all connected points.
2534  // - if the coupled master is on the patch it becomes the patch-point master
2535  // - else the slave with the lowest numbered patch point label
2536 
2537  // Get all data on master
2538  pointSlavesMap.distribute(coupledToGlobalPatch);
2539  forAll(pointSlaves, coupledPointi)
2540  {
2541  const labelList& slaves = pointSlaves[coupledPointi];
2542 
2543  if (slaves.size() > 0)
2544  {
2545  // I am master. What is the best candidate for patch-point master
2546  label masterI = labelMax;
2547  if (coupledToGlobalPatch[coupledPointi] != -1)
2548  {
2549  // I am master and on the coupled patch. Use me.
2550  masterI = coupledToGlobalPatch[coupledPointi];
2551  }
2552  else
2553  {
2554  // Get min of slaves as master.
2555  forAll(slaves, i)
2556  {
2557  label slavePp = coupledToGlobalPatch[slaves[i]];
2558  if (slavePp != -1 && slavePp < masterI)
2559  {
2560  masterI = slavePp;
2561  }
2562  }
2563  }
2564 
2565  if (masterI != labelMax)
2566  {
2567  // Push back
2568  coupledToGlobalPatch[coupledPointi] = masterI;
2569  forAll(slaves, i)
2570  {
2571  coupledToGlobalPatch[slaves[i]] = masterI;
2572  }
2573  }
2574  }
2575  }
2576  pointSlavesMap.reverseDistribute(cpp.nPoints(), coupledToGlobalPatch);
2577 
2578 
2579  // Generate compact numbering for master points
2580  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2581  // Now coupledToGlobalPatch is the globalIndex of the master point.
2582  // Now every processor can check whether they hold it and generate a
2583  // compact numbering.
2584 
2585  label nMasters = 0;
2586  forAll(meshPoints, patchPointi)
2587  {
2588  if (patchToCoupled[patchPointi] == -1)
2589  {
2590  nMasters++;
2591  }
2592  else
2593  {
2594  label coupledPointi = patchToCoupled[patchPointi];
2595  if
2596  (
2597  globalPPoints.toGlobal(patchPointi)
2598  == coupledToGlobalPatch[coupledPointi]
2599  )
2600  {
2601  // I am the master
2602  nMasters++;
2603  }
2604  }
2605  }
2606 
2607  autoPtr<globalIndex> globalPointsPtr(new globalIndex(nMasters));
2608 
2609  //Pout<< "Patch:" << nl
2610  // << " points:" << meshPoints.size() << nl
2611  // << " of which on coupled patch:" << nCoupled << nl
2612  // << " of which master:" << nMasters << endl;
2613 
2614 
2615 
2616  // Push back compact numbering for master point onto slaves
2617  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2618 
2619  pointToGlobal.setSize(meshPoints.size());
2620  pointToGlobal = -1;
2621  uniqueMeshPoints.setSize(nMasters);
2622 
2623  // Sync master in global point numbering so all know the master point.
2624  // Initialise globalMaster to be -1 except at a globalMaster.
2625  labelList globalMaster(cpp.nPoints(), -1);
2626 
2627  nMasters = 0;
2628  forAll(meshPoints, patchPointi)
2629  {
2630  if (patchToCoupled[patchPointi] == -1)
2631  {
2632  uniqueMeshPoints[nMasters++] = meshPoints[patchPointi];
2633  }
2634  else
2635  {
2636  label coupledPointi = patchToCoupled[patchPointi];
2637  if
2638  (
2639  globalPPoints.toGlobal(patchPointi)
2640  == coupledToGlobalPatch[coupledPointi]
2641  )
2642  {
2643  globalMaster[coupledPointi] =
2644  globalPointsPtr().toGlobal(nMasters);
2645  uniqueMeshPoints[nMasters++] = meshPoints[patchPointi];
2646  }
2647  }
2648  }
2649 
2650 
2651  // Sync by taking max
2652  syncData
2653  (
2654  globalMaster,
2655  pointSlaves,
2656  labelListList(0), // no transforms
2657  pointSlavesMap,
2658  maxEqOp<label>()
2659  );
2660 
2661 
2662  // Now everyone has the master point in globalPointsPtr numbering. Fill
2663  // in the pointToGlobal map.
2664  nMasters = 0;
2665  forAll(meshPoints, patchPointi)
2666  {
2667  if (patchToCoupled[patchPointi] == -1)
2668  {
2669  pointToGlobal[patchPointi] = globalPointsPtr().toGlobal(nMasters++);
2670  }
2671  else
2672  {
2673  label coupledPointi = patchToCoupled[patchPointi];
2674  pointToGlobal[patchPointi] = globalMaster[coupledPointi];
2675 
2676  if
2677  (
2678  globalPPoints.toGlobal(patchPointi)
2679  == coupledToGlobalPatch[coupledPointi]
2680  )
2681  {
2682  nMasters++;
2683  }
2684  }
2685  }
2686 
2687  return globalPointsPtr;
2688 }
2689 
2690 
2691 void Foam::globalMeshData::movePoints(const pointField& newPoints)
2692 {
2693  // Topology does not change and we don't store any geometry so nothing
2694  // needs to be done.
2695  // Only global transformations might change but this is not really
2696  // supported.
2697 }
2698 
2699 
2701 {
2702  // Clear out old data
2703  clearOut();
2704 
2705  // Do processor patch addressing
2706  initProcAddr();
2707 
2708  scalar tolDim = matchTol_ * mesh_.bounds().mag();
2709 
2710  if (debug)
2711  {
2712  Pout<< "globalMeshData : merge dist:" << tolDim << endl;
2713  }
2714 
2715  // *** Temporary hack to avoid problems with overlapping communication
2716  // *** between these reductions and the calculation of deltaCoeffs
2717  //const label comm = UPstream::worldComm + 1;
2718  const label comm = UPstream::allocateCommunicator
2719  (
2722  true
2723  );
2724  const label oldWarnComm = UPstream::warnComm;
2725  UPstream::warnComm = comm;
2726 
2727 
2728  // Total number of faces.
2729  nTotalFaces_ = returnReduce
2730  (
2731  mesh_.nFaces(),
2732  sumOp<label>(),
2734  comm
2735  );
2736 
2737  if (debug)
2738  {
2739  Pout<< "globalMeshData : nTotalFaces:" << nTotalFaces_ << endl;
2740  }
2741 
2742  nTotalCells_ = returnReduce
2743  (
2744  mesh_.nCells(),
2745  sumOp<label>(),
2747  comm
2748  );
2749 
2750  if (debug)
2751  {
2752  Pout<< "globalMeshData : nTotalCells:" << nTotalCells_ << endl;
2753  }
2754 
2755  nTotalPoints_ = returnReduce
2756  (
2757  mesh_.nPoints(),
2758  sumOp<label>(),
2760  comm
2761  );
2762 
2764  UPstream::warnComm = oldWarnComm;
2765 
2766  if (debug)
2767  {
2768  Pout<< "globalMeshData : nTotalPoints:" << nTotalPoints_ << endl;
2769  }
2770 }
2771 
2772 
2773 // ************************************************************************* //
const polyBoundaryMesh & boundaryMesh() const
Return boundary mesh.
Definition: polyMesh.H:584
const labelList & sharedPointLabels() const
Return indices of local points that are globally shared.
const Map< label > & coupledPatchMeshEdgeMap() const
Return map from mesh edges to coupledPatch edges.
List< labelList > labelListList
A List of labelList.
Definition: labelList.H:51
void reset(const label localSize, const label comm=UPstream::worldComm, const bool parallel=UPstream::parRun())
Reset from local size, using gather/broadcast with default/specified communicator if parallel...
Definition: globalIndex.C:188
const labelListList & globalPointSlaves() const
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:118
const mapDistribute & globalCoPointSlavesMap() const
"blocking" : (MPI_Bsend, MPI_Recv)
const labelListList & globalPointTransformedSlaves() const
pointField geometricSharedPoints() const
Like sharedPoints but keeps cyclic points separate.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
const globalIndex & globalBoundaryCellNumbering() const
Numbering of boundary cells is according to boundaryCells()
labelList pointLabels(nPoints, -1)
void resize(const label len)
Adjust allocated size of list.
Definition: ListI.H:132
const labelList & sharedPointGlobalLabels() const
Return shared point global labels. Tries to read.
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:578
const labelListList & globalPointTransformedBoundaryFaces() const
const mapDistribute & globalEdgeSlavesMap() const
static const Foam::scalar matchTol_
Geometric tolerance (fraction of bounding box)
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:49
void clearOut()
Remove all demand driven data.
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:639
const mapDistribute & globalPointSlavesMap() const
const bitSet & globalEdgeOrientation() const
Is my edge same orientation as master edge.
const labelListList & globalPointBoundaryCells() const
void resize_nocopy(const label len)
Adjust allocated size of list without necessarily.
Definition: ListI.H:139
static int & msgType() noexcept
Message tag of standard messages.
Definition: UPstream.H:806
autoPtr< globalIndex > mergePoints(labelList &pointToGlobal, labelList &uniquePoints) const
Helper for merging (collocated!) mesh point data.
const labelListList & globalEdgeSlaves() const
static int myProcNo(const label communicator=worldComm)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:688
tmp< DimensionedField< TypeR, GeoMesh > > New(const tmp< DimensionedField< TypeR, GeoMesh >> &tdf1, const word &name, const dimensionSet &dimensions, const bool initCopy=false)
Global function forwards to reuseTmpDimensionedField::New.
static label worldComm
Default world communicator (all processors). May differ from globalComm if local worlds are in use...
Definition: UPstream.H:361
const labelList & coupledPatchMeshEdges() const
Return map from coupledPatch edges to mesh edges.
PrimitivePatch< IndirectList< face >, const pointField & > indirectPrimitivePatch
A PrimitivePatch with an IndirectList for the faces, const reference for the point field...
static label allocateCommunicator(const label parent, const labelUList &subRanks, const bool doPstream=true)
Allocate a new communicator with subRanks of parent communicator.
Definition: UPstream.C:139
T returnReduce(const T &value, const BinaryOp &bop, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
Perform reduction on a copy, using specified binary operation.
const labelListList & globalPointBoundaryFaces() const
const dimensionedScalar me
Electron mass.
static bool less(const vector &x, const vector &y)
To compare normals.
UList< label > labelUList
A UList of labels.
Definition: UList.H:80
static void broadcast(Type &value, const label comm=UPstream::worldComm)
Broadcast content (contiguous or non-contiguous) to all processes in communicator.
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:413
const labelList & boundaryCells() const
From boundary cell to mesh cell.
label nGlobalEdges() const
Return number of globally shared edges. Demand-driven.
List helper to append y elements onto the end of x.
Definition: ListOps.H:680
scalar y
A list of faces which address into the list of points.
Calculates a unique integer (label so might not have enough room - 2G max) for processor + local inde...
Definition: globalIndex.H:63
const globalIndex & globalEdgeNumbering() const
static label nProcs(const label communicator=worldComm)
Number of ranks in parallel run (for given communicator) is 1 for serial run.
Definition: UPstream.H:656
label nGlobalPoints() const
Return number of globally shared points.
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:38
const labelList & sharedEdgeAddr() const
Return addressing into the complete globally shared edge.
const dimensionedScalar e
Elementary charge.
Definition: createFields.H:11
void setSize(const label n)
Alias for resize()
Definition: List.H:289
dynamicFvMesh & mesh
const globalIndexAndTransform & globalTransforms() const
Global transforms numbering.
List< edge > edgeList
A List of edges.
Definition: edgeList.H:60
static int compare(const Pair< label > &a, const Pair< label > &b)
Compare Pairs.
Definition: PairI.H:24
labelList identity(const label len, label start=0)
Return an identity map of the given length with (map[i] == i)
Definition: labelList.C:31
label nPoints
void sort(UList< T > &list)
Sort the list.
Definition: UList.C:334
static constexpr int masterNo() noexcept
Process index of the master (always 0)
Definition: UPstream.H:664
label size() const noexcept
The number of elements in the list.
Definition: UPtrListI.H:99
const globalIndex & globalPointNumbering() const
Numbering of coupled points is according to coupledPatch.
label inplaceMergePoints(PointList &points, const scalar mergeTol, const bool verbose, labelList &pointToUnique)
Inplace merge points, preserving the original point order. All points closer/equal mergeTol are to be...
List< labelPair > labelPairList
List of labelPairs.
Definition: labelPair.H:61
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:26
static label warnComm
Debugging: warn for use of any communicator differing from warnComm.
Definition: UPstream.H:366
errorManip< error > abort(error &err)
Definition: errorManip.H:139
static void combineReduce(const List< commsStruct > &comms, T &value, const CombineOp &cop, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
Reduce inplace (cf. MPI Allreduce) applying cop to inplace combine value from different processors...
void reset(const dimensionSet &ds)
Copy assign the exponents from the dimensionSet.
Definition: dimensionSet.C:142
int debug
Static debugging option.
Pair< label > labelPair
A pair of labels.
Definition: Pair.H:50
~globalMeshData()
Destructor.
defineTypeNameAndDebug(combustionModel, 0)
Geometric merging of points. See below.
labelList f(nPoints)
Define the processor-processor connection table by walking a list of patches and detecting the proces...
void movePoints(const pointField &newPoints)
Update for moving points.
const indirectPrimitivePatch & coupledPatch() const
Return patch of all coupled faces.
const labelListList & globalPointTransformedBoundaryCells() const
void operator()(T &x, const T &y) const
Definition: ops.H:76
Class containing processor-to-processor mapping information.
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
Definition: bitSet.H:59
static bool master(const label communicator=worldComm)
Am I the master rank.
Definition: UPstream.H:672
void updateMesh()
Change global mesh data given a topological change. Does a.
"nonBlocking" : (MPI_Isend, MPI_Irecv)
constexpr label labelMax
Definition: label.H:55
label n
static rangeType subProcs(const label communicator=worldComm)
Range of process indices for sub-processes.
Definition: UPstream.H:757
List< label > labelList
A List of labels.
Definition: List.H:62
const mapDistribute & globalPointBoundaryFacesMap() const
dimensionSet transform(const dimensionSet &ds)
Return the argument; transformations do not change the dimensions.
Definition: dimensionSet.C:529
const labelList & sharedPointAddr() const
Return addressing into the complete globally shared points.
Defines the attributes of an object for which implicit objectRegistry management is supported...
Definition: IOobject.H:166
pointField sharedPoints() const
Collect coordinates of shared points on all processors.
PrimitivePatch< List< face >, const pointField > bMesh
Holder of faceList and points. (v.s. e.g. primitivePatch which references points) ...
Definition: bMesh.H:42
const mapDistribute & globalPointBoundaryCellsMap() const
bool found
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
static void freeCommunicator(const label communicator, const bool doPstream=true)
Free a previously allocated communicator.
Definition: UPstream.C:239
const labelList & sharedEdgeLabels() const
Return indices of local edges that are globally shared.
Namespace for OpenFOAM.
forAllConstIters(mixture.phases(), phase)
Definition: pEqn.H:28
Determination and storage of the possible independent transforms introduced by coupledPolyPatches, as well as all of the possible permutations of these transforms generated by the presence of multiple coupledPolyPatches, i.e. more than one cyclic boundary. Note that any given point can be on maximum 3 transforms only (and these transforms have to be perpendicular)
const labelListList & globalCoPointSlaves() const
A HashTable to objects of type <T> with a label key.
const labelListList & globalEdgeTransformedSlaves() const
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:157
const globalIndex & globalBoundaryFaceNumbering() const
Numbering of boundary faces is face-mesh.nInternalFaces()