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