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