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-------------------------------------------------------------------------------
11License
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"
38#include "Pstream.H"
39
40// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
41
42namespace Foam
43{
45
46const scalar globalMeshData::matchTol_ = 1e-8;
47
48template<>
49class minEqOp<labelPair>
50{
51public:
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
63void 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
126void 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
246void 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
288void 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
503void 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
540void 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
644void 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
801Foam::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
859void 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],
979 globalIndexAndTransform::less(transforms)
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)
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
1079void 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
1207void 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
1277void 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
1468void 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
1692void 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
1731:
1732 mesh_(mesh),
1733 nTotalPoints_(-1),
1734 nTotalFaces_(-1),
1735 nTotalCells_(-1),
1736 processorTopology_
1737 (
1739 (
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{
1755 updateMesh();
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
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
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
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
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 (
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
2097const
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
2150const
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
2194const
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
2225const
2226{
2227 if (!globalBoundaryFaceNumberingPtr_)
2228 {
2229 calcGlobalPointBoundaryFaces();
2230 }
2231 return *globalBoundaryFaceNumberingPtr_;
2232}
2233
2234
2236const
2237{
2238 if (!globalPointBoundaryFacesPtr_)
2239 {
2240 calcGlobalPointBoundaryFaces();
2241 }
2242 return *globalPointBoundaryFacesPtr_;
2243}
2244
2245
2248{
2249 if (!globalPointTransformedBoundaryFacesPtr_)
2250 {
2251 calcGlobalPointBoundaryFaces();
2252 }
2253 return *globalPointTransformedBoundaryFacesPtr_;
2254}
2255
2256
2258const
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
2279const
2280{
2281 if (!globalBoundaryCellNumberingPtr_)
2282 {
2283 calcGlobalPointBoundaryCells();
2284 }
2285 return *globalBoundaryCellNumberingPtr_;
2286}
2287
2288
2290const
2291{
2292 if (!globalPointBoundaryCellsPtr_)
2293 {
2294 calcGlobalPointBoundaryCells();
2295 }
2296 return *globalPointBoundaryCellsPtr_;
2297}
2298
2299
2302{
2303 if (!globalPointTransformedBoundaryCellsPtr_)
2304 {
2305 calcGlobalPointBoundaryCells();
2306 }
2307 return *globalPointTransformedBoundaryCellsPtr_;
2308}
2309
2310
2312const
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,
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,
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
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// ************************************************************************* //
scalar y
bool found
label n
const_iterator cfind(const Key &key) const
Find and return an const_iterator set at the hashed entry.
Definition: HashTableI.H:141
bool insert(const Key &key, const T &obj)
Copy insert a new entry, not overwriting existing entries.
Definition: HashTableI.H:180
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition: IOobject.H:170
bool typeHeaderOk(const bool checkType=true, const bool search=true, const bool verbose=true)
Read header (uses typeFilePath to find file) and check its info.
Input inter-processor communications stream.
Definition: IPstream.H:57
A List with indirect addressing.
Definition: IndirectList.H:119
void setSize(const label n)
Alias for resize()
Definition: List.H:218
void resize_nocopy(const label len)
Adjust allocated size of list without necessarily.
Definition: ListI.H:146
void resize(const label len)
Adjust allocated size of list.
Definition: ListI.H:139
A HashTable to objects of type <T> with a label key.
Definition: Map.H:60
Output inter-processor communications stream.
Definition: OPstream.H:57
static int compare(const Pair< label > &a, const Pair< label > &b)
Compare Pairs.
Definition: PairI.H:31
A list of faces which address into the list of points.
label nPoints() const
Number of points supporting patch faces.
const Map< label > & meshPointMap() const
Mesh point map.
const labelList & meshPoints() const
Return labelList of mesh points in patch.
label nProcs() const noexcept
Number of ranks associated with PstreamBuffers.
UPstream::rangeType subProcs() const noexcept
Range of sub-processes indices associated with PstreamBuffers.
static void combineAllGather(const List< commsStruct > &comms, T &value, const CombineOp &cop, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
static void broadcast(Type &value, const label comm=UPstream::worldComm)
label find(const T &val, label pos=0) const
Find index of the first occurrence of the value.
Definition: UList.C:212
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
Inter-processor communications stream.
Definition: UPstream.H:59
@ nonBlocking
"nonBlocking"
static label warnComm
Debugging: warn for use of any communicator differing from warnComm.
Definition: UPstream.H:296
static void freeCommunicator(const label communicator, const bool doPstream=true)
Free a previously allocated communicator.
Definition: UPstream.C:174
static int & msgType() noexcept
Message tag of standard messages.
Definition: UPstream.H:556
static constexpr int masterNo() noexcept
Process index of the master (always 0)
Definition: UPstream.H:451
static label worldComm
Default communicator (all processors)
Definition: UPstream.H:293
static label allocateCommunicator(const label parent, const labelList &subRanks, const bool doPstream=true)
Allocate a new communicator.
Definition: UPstream.C:108
static bool & parRun() noexcept
Test if this a parallel run.
Definition: UPstream.H:433
label size() const noexcept
The number of elements in the list.
Definition: UPtrListI.H:106
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition: autoPtr.H:66
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
Definition: bitSet.H:66
bitSet & unset(const bitSet &other)
Definition: bitSetI.H:628
Addressing for all faces on surface of mesh. Can either be read from polyMesh or from triSurface....
Definition: boundaryMesh.H:63
void reset(const dimensionSet &ds)
Copy assign the exponents from the dimensionSet.
Definition: dimensionSet.C:149
Determination and storage of the possible independent transforms introduced by coupledPolyPatches,...
Calculates a unique integer (label so might not have enough room - 2G max) for processor + local inde...
Definition: globalIndex.H:68
void reset(const label localSize, const label comm=UPstream::worldComm, const bool parallel=UPstream::parRun())
Definition: globalIndex.C:207
label toGlobal(const label i) const
From local to global index.
Definition: globalIndexI.H:260
Various mesh related information for a parallel run. Upon construction, constructs all info using par...
const mapDistribute & globalCoPointSlavesMap() const
const labelList & sharedPointAddr() const
Return addressing into the complete globally shared points.
const bitSet & globalEdgeOrientation() const
Is my edge same orientation as master edge.
const labelListList & globalPointTransformedBoundaryCells() const
const labelListList & globalEdgeTransformedSlaves() const
const Map< label > & coupledPatchMeshEdgeMap() const
Return map from mesh edges to coupledPatch edges.
const labelList & sharedEdgeAddr() const
Return addressing into the complete globally shared edge.
pointField geometricSharedPoints() const
Like sharedPoints but keeps cyclic points separate.
static const Foam::scalar matchTol_
Geometric tolerance (fraction of bounding box)
label nGlobalPoints() const
Return number of globally shared points.
const mapDistribute & globalPointBoundaryCellsMap() const
const mapDistribute & globalPointBoundaryFacesMap() const
const mapDistribute & globalPointSlavesMap() const
const labelList & sharedPointLabels() const
Return indices of local points that are globally shared.
const labelListList & globalPointTransformedBoundaryFaces() const
const labelList & boundaryCells() const
From boundary cell to mesh cell.
const labelListList & globalPointBoundaryFaces() const
const mapDistribute & globalEdgeSlavesMap() const
const globalIndex & globalBoundaryFaceNumbering() const
Numbering of boundary faces is face-mesh.nInternalFaces()
label nGlobalEdges() const
Return number of globally shared edges. Demand-driven.
const labelList & coupledPatchMeshEdges() const
Return map from coupledPatch edges to mesh edges.
~globalMeshData()
Destructor.
autoPtr< globalIndex > mergePoints(labelList &pointToGlobal, labelList &uniquePoints) const
Helper for merging (collocated!) mesh point data.
const labelList & sharedPointGlobalLabels() const
Return shared point global labels. Tries to read.
const labelListList & globalCoPointSlaves() const
pointField sharedPoints() const
Collect coordinates of shared points on all processors.
const globalIndex & globalBoundaryCellNumbering() const
Numbering of boundary cells is according to boundaryCells()
const labelListList & globalPointSlaves() const
const globalIndex & globalEdgeNumbering() const
const globalIndexAndTransform & globalTransforms() const
Global transforms numbering.
const labelList & sharedEdgeLabels() const
Return indices of local edges that are globally shared.
const labelListList & globalPointTransformedSlaves() const
const indirectPrimitivePatch & coupledPatch() const
Return patch of all coupled faces.
void updateMesh()
Change global mesh data given a topological change. Does a.
const labelListList & globalPointBoundaryCells() const
void clearOut()
Remove all demand driven data.
const labelListList & globalEdgeSlaves() const
const globalIndex & globalPointNumbering() const
Numbering of coupled points is according to coupledPatch.
label constructSize() const noexcept
Constructed data size.
Class containing processor-to-processor mapping information.
void reverseDistribute(const label constructSize, List< T > &fld, const bool dummyTransform=true, const int tag=UPstream::msgType()) const
Reverse distribute data using default commsType.
void distribute(List< T > &fld, const bool dummyTransform=true, const int tag=UPstream::msgType()) const
Distribute data using default commsType.
void operator()(labelPair &x, const labelPair &y) const
void movePoints()
Update for new mesh geometry.
A polyBoundaryMesh is a polyPatch list with additional search methods and registered IO.
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:81
const polyBoundaryMesh & boundaryMesh() const
Return boundary mesh.
Definition: polyMesh.H:456
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:75
virtual bool coupled() const
Return true if this patch is geometrically coupled (i.e. faces and.
Definition: polyPatch.H:380
label start() const
Return start label of this patch in the polyMesh face list.
Definition: polyPatch.H:364
int myProcNo() const noexcept
Return processor number.
Neighbour processor patch.
Determines/represents processor-processor connection. After instantiation contains the processor-proc...
splitCell * master() const
Definition: splitCell.H:113
#define defineTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information.
Definition: className.H:121
dynamicFvMesh & mesh
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
const labelList nEdges(UPstream::listGatherValues< label >(aMesh.nEdges()))
label nPoints
Geometric merging of points. See below.
Namespace for OpenFOAM.
Pair< label > labelPair
A pair of labels.
Definition: Pair.H:57
List< labelPair > labelPairList
List of labelPairs.
Definition: labelPair.H:64
labelList identity(const label len, label start=0)
Return an identity map of the given length with (map[i] == i)
Definition: labelList.C:38
dimensionSet transform(const dimensionSet &ds)
Return the argument; transformations do not change the dimensions.
Definition: dimensionSet.C:536
List< label > labelList
A List of labels.
Definition: List.H:66
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:44
constexpr label labelMax
Definition: label.H:61
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:372
List< labelList > labelListList
A List of labelList.
Definition: labelList.H:56
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:33
void sort(UList< T > &list)
Sort the list.
Definition: UList.C:342
errorManip< error > abort(error &err)
Definition: errorManip.H:144
PrimitivePatch< List< face >, const pointField > bMesh
Holder of faceList and points. (v.s. e.g. primitivePatch which references points)
Definition: bMesh.H:48
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
tmp< DimensionedField< TypeR, GeoMesh > > New(const tmp< DimensionedField< TypeR, GeoMesh > > &tdf1, const word &name, const dimensionSet &dimensions)
Global function forwards to reuseTmpDimensionedField::New.
error FatalError
List< edge > edgeList
A List of edges.
Definition: edgeList.H:63
label inplaceMergePoints(PointList &points, const scalar mergeTol, const bool verbose, labelList &pointToUnique)
T returnReduce(const T &value, const BinaryOp &bop, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
Reduce (copy) and return value.
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
constexpr char nl
The newline '\n' character (0x0a)
Definition: Ostream.H:53
Define the processor-processor connection table by walking a list of patches and detecting the proces...
labelList f(nPoints)
labelList pointLabels(nPoints, -1)
volScalarField & e
Definition: createFields.H:11
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:333
#define forAllConstIters(container, iter)
Iterate across all elements of the container object with const access.
Definition: stdFoam.H:278
List helper to append y elements onto the end of x.
Definition: ListOps.H:563