faMeshDistributorNew.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) 2022 OpenCFD Ltd.
9-------------------------------------------------------------------------------
10License
11 This file is part of OpenFOAM.
12
13 OpenFOAM is free software: you can redistribute it and/or modify it
14 under the terms of the GNU General Public License as published by
15 the Free Software Foundation, either version 3 of the License, or
16 (at your option) any later version.
17
18 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25
26\*---------------------------------------------------------------------------*/
27
28#include "faMeshDistributor.H"
29#include "globalIndex.H"
30#include "BitOps.H"
31#include "ListOps.H"
33#include "processorFaPatch.H"
34#include "labelPairHashes.H"
35
36// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
37
40(
41 const faMesh& oldMesh,
42 const mapDistributePolyMesh& distMap,
43 const polyMesh& tgtPolyMesh,
44 autoPtr<faMesh>& newMeshPtr
45)
46{
47 newMeshPtr.reset(nullptr);
48
49 const uindirectPrimitivePatch& oldAreaPatch = oldMesh.patch();
50
51 // Original (patch) sizes before any changes
52 const label nOldPoints = oldAreaPatch.nPoints();
53 const label nOldEdges = oldAreaPatch.nEdges();
54 const label nOldFaces = oldAreaPatch.nFaces();
55
56
57 // ------------------------
58 // Step 1: The face mapping
59 // ------------------------
60 // Relatively straightforward.
61 // - a subset of face selections on the polyMesh faceMap
62
63 mapDistributeBase faFaceMap(distMap.faceMap());
64
65 {
66 // Retain faces needed for the faMesh - preserve original order
67
68 // Note can use compactLocalData without problem since
69 // finiteArea is only defined on real boundary faces so there
70 // is no danger of sending an internal or processor face.
71
72 labelList oldToNewSub;
73 labelList oldToNewConstruct;
74
75 faFaceMap.compactLocalData
76 (
77 oldMesh.faceLabels(),
78 oldToNewSub,
79 oldToNewConstruct,
80 distMap.nOldFaces(),
82 );
83
84
85 // The receiving side:
86 // Mapped faces (>= 0) are the polyMesh face labels that define
87 // the faMesh. Since the compact order is implicitly sorted in
88 // ascending order, it tends to form contiguous ranges on the
89 // polyPatches, which serves our purpose nicely.
90
91 labelList newFaceLabels
92 (
93 ListOps::findIndices(oldToNewConstruct, labelRange::ge0())
94 );
95
96 // Set up to read-if-present
97 IOobject io(tgtPolyMesh);
99
100 newMeshPtr.reset
101 (
102 new faMesh(tgtPolyMesh, std::move(newFaceLabels), io)
103 );
104 }
105
106 // The face map is now complete.
107
108 // The new faMesh and the corresponding primitive patch
109 auto& newMesh = newMeshPtr();
110 const uindirectPrimitivePatch& newAreaPatch = newMesh.patch();
111
112
113 // ------------------------
114 // Step 2: The edge mapping
115 // ------------------------
116 // Use globally unique addressing to identify both sides of the edges.
117
118 // A local bookkeeping struct of (face0 face1 edge0 edge1)
119 // selected for a stable and unique sort
120
121 struct faceEdgeTuple : public FixedList<label, 4>
122 {
123 // Inherit constructors
124 using FixedList<label, 4>::FixedList;
125
126 // Default construct as 'invalid'
127 faceEdgeTuple() : FixedList<label, 4>(-1) {}
128
129 // Is empty if face indices are negative
130 bool empty() const
131 {
132 return (face0() < 0 && face1() < 0);
133 }
134
135 // Global face numbers are the first sort index
136 label face0() const { return (*this)[0]; }
137 label face1() const { return (*this)[1]; }
138
139 // Additional sorting based on edges
140 label edge0() const { return (*this)[2]; }
141 label edge1() const { return (*this)[3]; }
142
143 label getFace(int i) const { return (*this)[(i ? 1 : 0)]; }
144 label getEdge(int i) const { return (*this)[(i ? 3 : 2)]; }
145
146 labelPair getFaces() const { return labelPair(face0(), face1()); }
147 labelPair getPair0() const { return labelPair(face0(), edge0()); }
148 // labelPair getPair1() const { return labelPair(face1(), edge1()); }
149
150 // Canonically sorted order
151 void canonical()
152 {
153 if (face1() >= 0 && face0() >= face1())
154 {
155 std::swap((*this)[0], (*this)[1]);
156 std::swap((*this)[2], (*this)[3]);
157 }
158 }
159
160 // Slot a face-edge pair into a free location in the tuple
161 void add(const labelPair& faceEdge)
162 {
163 if ((*this)[0] < 0) // face0
164 {
165 (*this)[0] = faceEdge.first(); // face
166 (*this)[2] = faceEdge.second(); // edge
167 }
168 else if ((*this)[1] < 0) // face1
169 {
170 (*this)[1] = faceEdge.first(); // face
171 (*this)[3] = faceEdge.second(); // edge
172 }
173 }
174
175 // Combine operation
176 void combine(const faceEdgeTuple& y)
177 {
178 auto& x = *this;
179
180 if (y.empty() || x == y)
181 {
182 // Nothing to do
183 }
184 else if (x.empty())
185 {
186 x = y;
187 }
188 else // Both non-empty, but non-identical (should not occur)
189 {
191 << "Unexpected edge matching: "
192 << x << " vs. " << y << endl
193 << exit(FatalError);
194 }
195 }
196
197 // Combine operation
198 void operator()(faceEdgeTuple& x, const faceEdgeTuple& y) const
199 {
200 x.combine(y);
201 }
202 };
203
204
205 // ------------------------
206 // (Edge mapping)
207 // ------------------------
208 // 1.
209 // Create a list of destination edges for each face,
210 // appended by a unique face identifier.
211 // Using global face numbering from the *target* mesh.
212
213 const globalIndex uniqFaceIndex(newAreaPatch.nFaces());
214
215 labelListList dstFaceEdgeIds(newAreaPatch.nFaces());
216
217 forAll(newAreaPatch.faceEdges(), facei)
218 {
219 const labelList& fEdges = newAreaPatch.faceEdges()[facei];
220 labelList& dstEdges = dstFaceEdgeIds[facei];
221
222 dstEdges.resize(fEdges.size() + 1);
223
224 // Leading entries are the destination (patch) edge indices
225 labelSubList(dstEdges, fEdges.size()) = fEdges;
226
227 // Last entry is the face id
228 dstEdges.last() = uniqFaceIndex.toGlobal(facei);
229 }
230
231 // Send back to the original mesh locations
232 faFaceMap.reverseDistribute(nOldFaces, dstFaceEdgeIds);
233
234
235 // 2.
236 // Walk all original faces and their edges to generate a edge lookup
237 // table with the destination face/edge information.
238 // Eg ((globFacei, localEdgei), (globFacei, localEdgei))
239
240 // NB: currently no provision for face flips, which would potentially
241 // reverse the local edge order.
242
243 List<faceEdgeTuple> halfEdgeLookup(nOldEdges, faceEdgeTuple());
244
245 forAll(oldAreaPatch.faceEdges(), facei)
246 {
247 const labelList& fEdges = oldAreaPatch.faceEdges()[facei];
248
249 // The corresponding destination edges (+ uniqFacei).
250 const labelList& dstFaceEdges = dstFaceEdgeIds[facei];
251
252 // Last entry has the unique destination face id
253 const label uniqFacei = dstFaceEdges.last();
254
255 forAll(fEdges, faceEdgei)
256 {
257 const label srcEdgei = fEdges[faceEdgei];
258 const label dstEdgei = dstFaceEdges[faceEdgei];
259
260 halfEdgeLookup[srcEdgei].add(labelPair(uniqFacei, dstEdgei));
261 }
262 }
263
264 // 3.
265 // Add patch indices - encoded as '-(patchId + 2)' for
266 // non-processor boundaries (will be needed later).
267
268 // Also record which procs get patches from here [proc] -> [patches]
269 // Use for building patchMap
270 Map<labelHashSet> patchMapInfo;
271
272 label nNonProcessor(0);
273 {
274 const faBoundaryMesh& oldBndMesh = oldMesh.boundary();
275
276 forAll(oldBndMesh, patchi)
277 {
278 const faPatch& fap = oldBndMesh[patchi];
279 if (isA<processorFaPatch>(fap))
280 {
281 break;
282 }
284
285 // Encoded as -(patchId + 2)
286 const labelPair encodedPatchId(-(patchi+2), -(patchi+2));
287
288 for (const label srcEdgei : fap.edgeLabels())
289 {
290 faceEdgeTuple& facePairings = halfEdgeLookup[srcEdgei];
291
292 facePairings.add(encodedPatchId);
293
294 label dstFacei = facePairings.face0();
295
296 label proci = uniqFaceIndex.whichProcID(dstFacei);
297
298 patchMapInfo(proci).insert(patchi);
299 }
300 }
301
303 }
304
305 // Processor-processor connections
306 if (Pstream::parRun())
307 {
308 const label startOfRequests = Pstream::nRequests();
309
310 const faBoundaryMesh& oldBndMesh = oldMesh.boundary();
311
312 // Setup sends
313 for (const faPatch& fap : oldBndMesh)
314 {
315 const auto* fapp = isA<processorFaPatch>(fap);
316
317 if (fapp)
318 {
319 // Send (dstFacei dstEdgei) per patch edge.
320 // Since we are walking a boundary edge, the first location
321 // from the previously established lookup provides
322 // our information.
323
324 List<labelPair> edgeTuples(fap.edgeLabels().size());
325
326 label edgeTuplei = 0;
327
328 for (const label edgei : fap.edgeLabels())
329 {
330 edgeTuples[edgeTuplei] = halfEdgeLookup[edgei].getPair0();
331 ++edgeTuplei;
332 }
333
334 fapp->send<labelPair>
335 (
337 edgeTuples
338 );
339 }
340 }
341
342 // Wait for all to finish
343 Pstream::waitRequests(startOfRequests);
344
345 // Receive values
346 for (const faPatch& fap : oldBndMesh)
347 {
348 const auto* fapp = isA<processorFaPatch>(fap);
349
350 if (fapp)
351 {
352 // Receive (dstFacei dstEdgei) per patch edge.
353 // - slot into the second location of the lookup
354
355 List<labelPair> edgeTuples(fap.edgeLabels().size());
356
357 fapp->receive<labelPair>
358 (
360 edgeTuples
361 );
362
363 label edgeTuplei = 0;
364
365 for (const label srcEdgei : fap.edgeLabels())
366 {
367 halfEdgeLookup[srcEdgei].add(edgeTuples[edgeTuplei]);
368 ++edgeTuplei;
369 }
370 }
371 }
372 }
373
374 // Globally consistent order
375 for (auto& tuple : halfEdgeLookup)
376 {
377 tuple.canonical();
378 }
379
380
381 // Now ready to actually construct the edgeMap
382
383 mapDistributeBase faEdgeMap
384 (
385 newAreaPatch.nEdges(), // constructSize
386 labelListList(), // subMap
387 labelListList(), // constructMap
388 false, // subHasFlip
389 false, // constructHasFlip
390 faFaceMap.comm()
391 );
392
393 {
394 // Pass 1.
395 // Count the number of edges to be sent to each proc
396
398
399 forAll(halfEdgeLookup, srcEdgei)
400 {
401 const faceEdgeTuple& facePairings = halfEdgeLookup[srcEdgei];
402
403 labelPair dstProcs(-1, -1);
404
405 for (int sidei = 0; sidei < 2; ++sidei)
406 {
407 const label dstFacei = facePairings.getFace(sidei);
408 //const label dstEdgei = facePairings.getEdge(sidei);
409
410 if (dstFacei < 0)
411 {
412 continue;
413 }
414
415 label proci = uniqFaceIndex.whichProcID(dstFacei);
416 dstProcs[sidei] = proci;
417
418 if (proci != -1 && dstProcs[0] != dstProcs[1])
419 {
420 ++nProcEdges[proci];
421 }
422 }
423 }
424
425 auto& edgeSubMap = faEdgeMap.subMap();
426 auto& edgeCnstrMap = faEdgeMap.constructMap();
427
428 edgeSubMap.resize(nProcEdges.size());
429 edgeCnstrMap.resize(nProcEdges.size());
430
431 labelListList remoteEdges(nProcEdges.size());
432
433 forAll(nProcEdges, proci)
434 {
435 edgeSubMap[proci].resize(nProcEdges[proci], -1);
436 remoteEdges[proci].resize(nProcEdges[proci], -1);
437 }
438
439
440 // Pass 2.
441 // Fill in the maps
442
443 nProcEdges = Zero; // Reset counter
444
445 forAll(halfEdgeLookup, srcEdgei)
446 {
447 const faceEdgeTuple& facePairings = halfEdgeLookup[srcEdgei];
448
449 labelPair dstProcs(-1, -1);
450
451 for (int sidei = 0; sidei < 2; ++sidei)
452 {
453 const label dstFacei = facePairings.getFace(sidei);
454 const label dstEdgei = facePairings.getEdge(sidei);
455
456 if (dstFacei < 0)
457 {
458 continue;
459 }
460
461 label proci = uniqFaceIndex.whichProcID(dstFacei);
462 dstProcs[sidei] = proci;
463
464 if (proci != -1 && dstProcs[0] != dstProcs[1])
465 {
466 edgeSubMap[proci][nProcEdges[proci]] = srcEdgei;
467 remoteEdges[proci][nProcEdges[proci]] = dstEdgei;
468 ++nProcEdges[proci];
469 }
470 }
471 }
472
473 // The remoteEdges are what we know locally about what will be
474 // received, but not what is actually received.
475 // So need an all-to-all exchange
476
477 Pstream::exchange<labelList, label>
478 (
479 remoteEdges,
480 edgeCnstrMap,
482 faEdgeMap.comm()
483 );
484 }
485
486 // The edge map is now complete [in PrimitivePatch edge order]
487
488
489 if (oldMesh.hasInternalEdgeLabels())
490 {
491 // If there are gaps in the edge numbering or the
492 // internal edge labels are out of sequence would
493 // have to use compactLocalData etc before sending
494 // But just issue an error for now
495
497 << "Originating faMesh has gaps in the edge addressing"
498 << " this is currently unsupported"
499 << abort(FatalError);
500 }
501
502
503 // ------------------------
504 // Patch edge labels
505 // ------------------------
506
507 faPatchList newFaPatches;
508
509 // Distribute the edge lookups.
510 // Needs full version for the combine operation
511
512 mapDistributeBase::distribute<faceEdgeTuple, faceEdgeTuple, identityOp>
513 (
516 faEdgeMap.constructSize(),
517
518 faEdgeMap.subMap(),
519 faEdgeMap.subHasFlip(),
520
521 faEdgeMap.constructMap(),
522 faEdgeMap.constructHasFlip(),
523
524 halfEdgeLookup,
525 faceEdgeTuple(), // nullValue
526 faceEdgeTuple(), // CombineOp
527 identityOp(), // NegateOp
529 faEdgeMap.comm()
530 );
531
532 {
533 // Pass 1.
534 // Count the number of edges for each patch type
535
536 Map<label> nNonProcEdges(2*nNonProcessor);
538
539 forAll(halfEdgeLookup, edgei)
540 {
541 const auto& tuple = halfEdgeLookup[edgei];
542
543 labelPair target(tuple.getFaces());
544
545 if (target[1] < -1)
546 {
547 // Neighbour face was patchId encoded value
548 label patchi = mag(target[1])-2;
549 ++nNonProcEdges(patchi);
550 }
551 else if (target[0] >= 0 && target[1] >= 0)
552 {
553 // From global face to proc id
554 target[0] = uniqFaceIndex.whichProcID(target[0]);
555 target[1] = uniqFaceIndex.whichProcID(target[1]);
556
557 // A connection between different procs but involving
558 // myProc?
559 if
560 (
561 target[0] != target[1]
562 &&
563 (
564 target[0] == Pstream::myProcNo()
565 || target[1] == Pstream::myProcNo()
566 )
567 )
568 {
569 ++nProcEdges(target);
570 }
571 }
572 }
573
575
576 newFaPatches.resize(nPatches);
577
578 labelList nEdgeLabels(nPatches, Zero);
579 labelListList newEdgeLabels(nPatches);
580
581 LabelPairMap<label> procPairToPatchId(2*nProcEdges.size());
582
583 // Map processor-pair to index in patches
584 {
586
587 for (const labelPair& twoProcs : nProcEdges.sortedToc())
588 {
589 procPairToPatchId.set(twoProcs, nPatches);
590 ++nPatches;
591 }
592 }
593
594 // Presize edgeLabels arrays
595 {
596 nPatches = 0;
597
598 for (label patchi = 0; patchi < nNonProcessor; ++patchi)
599 {
600 label nLabels = nNonProcEdges.lookup(nPatches, 0);
601
602 nEdgeLabels[nPatches] = nLabels;
603
604 newEdgeLabels[nPatches].resize(nLabels);
605
606 ++nPatches;
607 }
608
609 // Processor patches
610 for (const labelPair& twoProcs : nProcEdges.sortedToc())
611 {
612 label nLabels = nProcEdges.lookup(twoProcs, 0);
613
614 nEdgeLabels[nPatches] = nLabels;
615
616 newEdgeLabels[nPatches].resize(nLabels);
617
618 ++nPatches;
619 }
620 }
621
622 nEdgeLabels = Zero;
623
624 // Populate edgeLabels arrays - walk in canonically sorted
625 // order to ensure that both sides of processor edges
626 // correspond.
627
628 const labelList order(Foam::sortedOrder(halfEdgeLookup));
629
630 for (const label edgei : order)
631 {
632 const auto& tuple = halfEdgeLookup[edgei];
633
634 labelPair target(tuple.getFaces());
635
636 label patchi = -1;
637
638 if (target[1] < -1)
639 {
640 // Neighbour face was patchId encoded value
641 patchi = mag(target[1])-2;
642 }
643 else if (target[0] >= 0 && target[1] >= 0)
644 {
645 // From global face to proc id
646 target[0] = uniqFaceIndex.whichProcID(target[0]);
647 target[1] = uniqFaceIndex.whichProcID(target[1]);
648
649 // A connection between different procs but involving
650 // myProc?
651 if
652 (
653 target[0] != target[1]
654 &&
655 (
656 target[0] == Pstream::myProcNo()
657 || target[1] == Pstream::myProcNo()
658 )
659 )
660 {
661 patchi = procPairToPatchId.lookup(target, -1);
662 }
663 }
664
665 if (patchi >= 0)
666 {
667 const label idx = nEdgeLabels[patchi]++;
668 newEdgeLabels[patchi][idx] = edgei;
669 }
670 }
671
672
673 // Clone all non-processor patches
674
675 nPatches = 0;
676 for (label patchi = 0; patchi < nNonProcessor; ++patchi)
677 {
678 newFaPatches.set
679 (
680 nPatches,
681 oldMesh.boundary()[patchi].clone
682 (
683 newMesh.boundary(),
684 newEdgeLabels[nPatches], // edgeLabels
685 nPatches,
686 oldMesh.boundary()[patchi].ngbPolyPatchIndex()
687 )
688 );
689 ++nPatches;
690 }
691
692 // Any processor patches
693 for (const labelPair& twoProcs : nProcEdges.sortedToc())
694 {
695 label nbrProcNo =
696 (
697 twoProcs[1] == Pstream::myProcNo()
698 ? twoProcs[0] : twoProcs[1]
699 );
700
701 newFaPatches.set
702 (
703 nPatches,
705 (
706 newEdgeLabels[nPatches], // edgeLabels
707 nPatches,
708 newMesh.boundary(),
709 -1, // nbrPolyPatchi
711 nbrProcNo
712 )
713 );
714 ++nPatches;
715 }
716 }
717
718
719 newMesh.addFaPatches(newFaPatches);
720 newMesh.init(true);
721
722
723 // At this stage we now have a complete mapping overview in
724 // terms of the PrimitivePatch edge ordering which now must be
725 // changed into faMesh edge ordering.
726
727 {
728 labelList oldToNewSub;
729 labelList oldToNewConstruct;
730
731 // Assume we use all patch edges for the faMesh too.
732 oldToNewSub.resize(oldAreaPatch.nEdges(), -1);
733 oldToNewConstruct.resize(newAreaPatch.nEdges(), -1);
734
735 // Remap old edges
736 label nEdges = 0;
737
738 // Internal edgeLabels
739 for
740 (
741 label edgei = 0;
742 edgei < oldAreaPatch.nInternalEdges();
743 ++edgei
744 )
745 {
746 oldToNewSub[edgei] = nEdges++;
747 }
748
749 // Boundary edgeLabels
750 for (const faPatch& fap : oldMesh.boundary())
751 {
752 for (const label edgei : fap.edgeLabels())
753 {
754 oldToNewSub[edgei] = nEdges++;
755 }
756 }
757
758 // New edges
759 nEdges = 0;
760
761 // Internal edgeLabels
762 for
763 (
764 label edgei = 0;
765 edgei < newAreaPatch.nInternalEdges();
766 ++edgei
767 )
768 {
769 oldToNewConstruct[edgei] = nEdges++;
770 }
771
772 // Boundary edgeLabels
773 for (const faPatch& fap : newMesh.boundary())
774 {
775 for (const label edgei : fap.edgeLabels())
776 {
777 oldToNewConstruct[edgei] = nEdges++;
778 }
779 }
780
782 (
783 faEdgeMap.subMap(),
784 oldToNewSub,
785 faEdgeMap.subHasFlip()
786 );
787
789 (
790 faEdgeMap.constructMap(),
791 oldToNewConstruct,
792 faEdgeMap.constructHasFlip()
793 );
794 }
795
796
797 // ------------------------
798 // Patch mapping
799 // ------------------------
800
801 mapDistributeBase faPatchMap
802 (
803 newMesh.boundary().size(), // constructSize
804 labelListList(), // subMap
805 labelListList(), // constructMap
806 false, // subHasFlip
807 false, // constructHasFlip
808 faFaceMap.comm()
809 );
810
811 // For patch maps, would normally transcribe from patchMapInfo
812 // gathered earlier. However, existing practice (APR-2022) for
813 // faMesh decomposition is to map all non-processor patches
814
815 {
816 // Map all non-processor patches
817 const label nProcs = UPstream::nProcs(faPatchMap.comm());
818
819 faPatchMap.subMap().resize(nProcs, identity(nNonProcessor));
820 faPatchMap.constructMap().resize(nProcs, identity(nNonProcessor));
821 }
822
852
853
854 // ------------------------
855 // Point mapping
856 // ------------------------
857
858 mapDistributeBase faPointMap(distMap.pointMap());
859
860 {
861 // Retain meshPoints needed for the faMesh - preserve original order
862 // Need both sides (local/remote) for correct compaction maps
863 // without dangling points.
864
865 labelList oldToNewSub;
866 labelList oldToNewConstruct;
867
868 faPointMap.compactData
869 (
870 oldAreaPatch.meshPoints(),
871 newAreaPatch.meshPoints(),
872 oldToNewSub,
873 oldToNewConstruct,
874 distMap.nOldPoints(),
876 );
877 }
878
879
881 (
882 // Mesh before changes
883 nOldPoints,
884 nOldEdges, // area: nOldEdges (volume: nOldFaces)
885 nOldFaces, // area: nOldFaces (volume: nOldCells)
886
887 labelList(oldMesh.boundary().patchStarts()),
888 labelList(), // oldPatchNMeshPoints [unused]
889
890 mapDistribute(std::move(faPointMap)),
891 mapDistribute(std::move(faEdgeMap)), // area: edgeMap (volume: faceMap)
892 mapDistribute(std::move(faFaceMap)), // area: faceMap (volume: cellMap)
893 mapDistribute(std::move(faPatchMap))
894 );
895}
896
897
900(
901 const faMesh& oldMesh,
902 const mapDistributePolyMesh& distMap,
903 autoPtr<faMesh>& newMeshPtr
904)
905{
906 return faMeshDistributor::distribute
907 (
908 oldMesh,
909 distMap,
910 oldMesh.mesh(), // polyMesh
911 newMeshPtr
912 );
913}
914
915
916// ************************************************************************* //
scalar y
Various functions to operate on Lists.
A 1D vector of objects of type <T> with a fixed length <N>.
Definition: FixedList.H:81
T & first() noexcept
The first element of the list, position [0].
Definition: FixedListI.H:207
A HashTable similar to std::unordered_map.
Definition: HashTable.H:123
bool set(const Key &key, const T &obj)
Copy assign a new entry, overwriting existing entries.
Definition: HashTableI.H:202
const T & lookup(const Key &key, const T &deflt) const
Return hashed entry if it exists, or return the given default.
Definition: HashTableI.H:224
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
readOption readOpt() const noexcept
The read option.
Definition: IOobjectI.H:164
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
const T & second() const noexcept
Return second element, which is also the last element.
Definition: PairI.H:120
A list of faces which address into the list of points.
label nEdges() const
Number of edges in patch.
label nPoints() const
Number of points supporting patch faces.
label nFaces() const noexcept
Number of faces in the patch.
label nInternalEdges() const
Number of internal edges.
const labelList & meshPoints() const
Return labelList of mesh points in patch.
const labelListList & faceEdges() const
Return face-edge addressing.
label nProcs() const noexcept
Number of ranks associated with PstreamBuffers.
static void broadcast(Type &value, const label comm=UPstream::worldComm)
A list of pointers to objects of type <T>, with allocation/deallocation management of the pointers....
Definition: PtrList.H:73
const T * set(const label i) const
Definition: PtrList.H:138
PtrList< T > clone(Args &&... args) const
Make a copy by cloning each of the list elements.
void resize(const label newLen)
Adjust size of PtrList.
Definition: PtrList.C:103
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
T & last()
Return the last element of the list.
Definition: UListI.H:216
@ nonBlocking
"nonBlocking"
static int & msgType() noexcept
Message tag of standard messages.
Definition: UPstream.H:556
static label nRequests()
Get number of outstanding requests.
Definition: UPstream.C:90
static void waitRequests(const label start=0)
Wait until all requests (from start onwards) have finished.
Definition: UPstream.C:100
static bool & parRun() noexcept
Test if this a parallel run.
Definition: UPstream.H:433
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition: autoPtr.H:66
void reset(autoPtr< T > &&other) noexcept
Delete managed object and set to new given pointer.
Definition: autoPtrI.H:117
Finite area boundary mesh.
labelList patchStarts() const
Return a list of patch start indices.
static mapDistributePolyMesh distribute(const faMesh &oldMesh, const mapDistributePolyMesh &distMap, const polyMesh &tgtPolyMesh, autoPtr< faMesh > &newMeshPtr)
Distribute mesh according to the given (volume) mesh distribution.
Finite area mesh (used for 2-D non-Euclidian finite area method) defined using a patch of faces on a ...
Definition: faMesh.H:100
bool hasInternalEdgeLabels() const noexcept
Definition: faMeshI.H:148
const faBoundaryMesh & boundary() const noexcept
Return constant reference to boundary mesh.
Definition: faMeshI.H:38
const polyMesh & mesh() const
Return access to polyMesh.
Definition: faMeshI.H:31
const uindirectPrimitivePatch & patch() const
Return constant reference to primitive patch.
Definition: faMeshI.H:128
const labelList & faceLabels() const noexcept
Return the underlying polyMesh face labels.
Definition: faMeshI.H:122
Finite area patch class. Used for 2-D non-Euclidian finite area method.
Definition: faPatch.H:78
const labelList & edgeLabels() const noexcept
Return the list of edges.
Definition: faPatch.H:275
Calculates a unique integer (label so might not have enough room - 2G max) for processor + local inde...
Definition: globalIndex.H:68
label toGlobal(const label i) const
From local to global index.
Definition: globalIndexI.H:260
Class containing processor-to-processor mapping information.
static label renumberMap(labelListList &mapElements, const labelUList &oldToNew, const bool hasFlip)
const labelListList & constructMap() const noexcept
From subsetted data to new reconstructed data.
void reverseDistribute(const label constructSize, List< T > &values, const int tag=UPstream::msgType()) const
bool constructHasFlip() const noexcept
Does constructMap include a sign.
const labelListList & subMap() const noexcept
From subsetted data back to original data.
bool subHasFlip() const noexcept
Does subMap include a sign.
label comm() const noexcept
The communicator used.
label constructSize() const noexcept
Constructed data size.
void compactLocalData(const bitSet &allowedLocalElems, const int tag=UPstream::msgType(), const bool doRenumber=false)
Class containing mesh-to-mesh mapping information after a mesh distribution where we send parts of me...
label nOldFaces() const noexcept
Number of faces in mesh before distribution.
const mapDistribute & pointMap() const noexcept
Point distribute map.
const mapDistribute & faceMap() const noexcept
Face distribute map.
label nOldPoints() const noexcept
Number of points in mesh before distribution.
Class containing processor-to-processor mapping information.
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:81
int myProcNo() const noexcept
Return processor number.
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
const label nNonProcessor
const labelList nProcEdges(UPstream::listGatherValues< label >(nLocalProcEdges))
const label nPatches
const labelList nEdges(UPstream::listGatherValues< label >(aMesh.nEdges()))
A HashTable to objects of type <T> with a labelPair key. The hashing is based on labelPair (FixedList...
IOobject io("surfaceFilmProperties", mesh.time().constant(), mesh, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE, false)
labelList findIndices(const ListType &input, const UnaryPredicate &pred, label start=0)
Linear search to find all occurences of given element.
Pair< label > labelPair
A pair of labels.
Definition: Pair.H:57
labelList identity(const label len, label start=0)
Return an identity map of the given length with (map[i] == i)
Definition: labelList.C:38
List< label > labelList
A List of labels.
Definition: List.H:66
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:372
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
List< labelList > labelListList
A List of labelList.
Definition: labelList.H:56
labelList sortedOrder(const UList< T > &input)
Return the (stable) sort order for the list.
SubList< label > labelSubList
A SubList of labels.
Definition: SubList.H:59
errorManip< error > abort(error &err)
Definition: errorManip.H:144
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
error FatalError
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
dict add("bounds", meshBb)
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:333
Unary predicate for greater-equal 0 (int values)
Definition: IntRange.H:130