Loading...
Searching...
No Matches
lduPrimitiveMesh.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) 2013-2017 OpenFOAM Foundation
9 Copyright (C) 2019-2023 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 "lduPrimitiveMesh.H"
32#include "edgeHashes.H"
33#include "labelPair.H"
35
36// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
37
38namespace Foam
40 defineTypeNameAndDebug(lduPrimitiveMesh, 0);
41}
42
43
44// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
45
47(
48 const label size,
49 const labelUList& l,
50 const labelUList& u
51)
52{
53 forAll(l, facei)
54 {
55 if (u[facei] < l[facei])
56 {
58 << "Reversed face. Problem at face " << facei
59 << " l:" << l[facei] << " u:" << u[facei]
60 << abort(FatalError);
61 }
62 if (l[facei] < 0 || u[facei] < 0 || u[facei] >= size)
63 {
65 << "Illegal cell label. Problem at face " << facei
66 << " l:" << l[facei] << " u:" << u[facei]
67 << abort(FatalError);
68 }
69 }
70
71 for (label facei=1; facei < l.size(); ++facei)
72 {
73 if (l[facei-1] > l[facei])
74 {
76 << "Lower not in incremental cell order."
77 << " Problem at face " << facei
78 << " l:" << l[facei] << " u:" << u[facei]
79 << " previous l:" << l[facei-1]
80 << abort(FatalError);
81 }
82 else if (l[facei-1] == l[facei])
83 {
84 // Same cell.
85 if (u[facei-1] > u[facei])
86 {
88 << "Upper not in incremental cell order."
89 << " Problem at face " << facei
90 << " l:" << l[facei] << " u:" << u[facei]
91 << " previous u:" << u[facei-1]
93 }
94 }
95 }
96}
97
98
100(
101 const lduMesh& mesh,
102 const globalIndex& globalNumbering
103)
104{
105 const lduAddressing& addr = mesh.lduAddr();
106 lduInterfacePtrsList interfaces = mesh.interfaces();
107
108 const label myProci = UPstream::myProcNo(mesh.comm());
109
110 const labelList globalIndices
111 (
113 (
114 addr.size(),
115 globalNumbering.localStart(myProci)
116 )
117 );
118
119 // Get the interface cells
120 PtrList<labelList> nbrGlobalCells(interfaces.size());
121 {
122 const label startOfRequests = UPstream::nRequests();
123
124 // Initialise transfer of restrict addressing on the interface
125 forAll(interfaces, inti)
126 {
127 if (interfaces.set(inti))
128 {
129 interfaces[inti].initInternalFieldTransfer
130 (
132 globalIndices
133 );
134 }
135 }
136
137 UPstream::waitRequests(startOfRequests);
138
139 forAll(interfaces, inti)
140 {
141 if (interfaces.set(inti))
142 {
143 nbrGlobalCells.set
144 (
145 inti,
146 new labelList
147 (
148 interfaces[inti].internalFieldTransfer
149 (
151 globalIndices
152 )
153 )
154 );
155 }
156 }
157 }
158
159
160 // Scan the neighbour list to find out how many times the cell
161 // appears as a neighbour of the face. Done this way to avoid guessing
162 // and resizing list
163 labelList nNbrs(addr.size(), Zero);
164
165 const labelUList& nbr = addr.upperAddr();
166 const labelUList& own = addr.lowerAddr();
167
168 {
169 forAll(nbr, facei)
170 {
171 nNbrs[nbr[facei]]++;
172 nNbrs[own[facei]]++;
173 }
174
175 forAll(interfaces, inti)
176 {
177 if (interfaces.set(inti))
178 {
179 for (const label celli : interfaces[inti].faceCells())
180 {
181 nNbrs[celli]++;
182 }
183 }
184 }
185 }
186
187
188 // Create cell-cells addressing
189 labelListList cellCells(addr.size());
190
191 forAll(cellCells, celli)
192 {
193 cellCells[celli].setSize(nNbrs[celli], -1);
194 }
195
196 // Reset the list of number of neighbours to zero
197 nNbrs = 0;
198
199 // Scatter the neighbour faces
200 forAll(nbr, facei)
201 {
202 const label c0 = own[facei];
203 const label c1 = nbr[facei];
204
205 cellCells[c0][nNbrs[c0]++] = globalIndices[c1];
206 cellCells[c1][nNbrs[c1]++] = globalIndices[c0];
207 }
208 forAll(interfaces, inti)
209 {
210 if (interfaces.set(inti))
211 {
212 const labelUList& faceCells = interfaces[inti].faceCells();
213
214 forAll(faceCells, facei)
215 {
216 const label c0 = faceCells[facei];
217 cellCells[c0][nNbrs[c0]++] = nbrGlobalCells[inti][facei];
218 }
219 }
220 }
221
222 return cellCells;
223}
224
225
226Foam::label Foam::lduPrimitiveMesh::totalSize
227(
229)
230{
231 label size = 0;
232
233 for (const lduPrimitiveMesh& msh : meshes)
235 size += msh.lduAddr().size();
236 }
237 return size;
238}
239
240
242(
243 const label nCells,
244 const labelUList& lower,
245 const labelUList& upper
246)
247{
248 labelList nNbrs(nCells, Zero);
249
250 // Count number of upper neighbours
251 forAll(lower, facei)
252 {
253 if (upper[facei] < lower[facei])
254 {
256 << "Problem at face:" << facei
257 << " lower:" << lower[facei]
258 << " upper:" << upper[facei]
259 << exit(FatalError);
260 }
261 nNbrs[lower[facei]]++;
262 }
263
264 // Construct cell-upper cell addressing
265 labelList offsets(nCells+1);
266 offsets[0] = 0;
267 forAll(nNbrs, celli)
268 {
269 offsets[celli+1] = offsets[celli]+nNbrs[celli];
270 }
271
272 nNbrs = offsets;
273
274 labelList cellToFaces(offsets.last());
275 forAll(upper, facei)
276 {
277 const label celli = lower[facei];
278 cellToFaces[nNbrs[celli]++] = facei;
279 }
280
281 // Sort
282
283 labelList oldToNew(lower.size());
284
285 DynamicList<label> order;
287
288 label newFacei = 0;
289
290 for (label celli = 0; celli < nCells; ++celli)
291 {
292 const label startOfCell = offsets[celli];
293 const label nNbr = offsets[celli+1] - startOfCell;
294
295 nbr.resize(nNbr);
296 order.resize(nNbr);
297
298 forAll(nbr, i)
299 {
300 nbr[i] = upper[cellToFaces[offsets[celli]+i]];
301 }
302 sortedOrder(nbr, order);
303
304 for (const label index : order)
305 {
306 oldToNew[cellToFaces[startOfCell + index]] = newFacei++;
307 }
308 }
309
310 return oldToNew;
311}
312
313
314Foam::label Foam::lduPrimitiveMesh::findConnectedInterface
315(
316 const lduMesh& myMesh,
317 const PtrList<lduPrimitiveMesh>& otherMeshes,
318 const labelPairList& procAndInterfaces,
319
320 const label nbrProci,
321 const label myRank
322) const
323{
324 // Find mesh, interfacei in procAndInterfaces
325 label nbrInti = -1;
326 for (const auto& procAndInterface : procAndInterfaces)
327 {
328 const label proci = procAndInterface[0];
329
330 if (proci == nbrProci)
331 {
332 const label interfacei = procAndInterface[1];
333 const lduInterfacePtrsList interfaces =
334 mesh
335 (
336 myMesh,
337 otherMeshes,
338 proci
339 ).interfaces();
340 const processorLduInterface& pldui =
342 (
343 interfaces[interfacei]
344 );
345
346 if (pldui.neighbProcNo() == myRank)
347 {
348 nbrInti = procAndInterface[1];
349 break;
350 }
351 }
352 }
353
354
355 if (nbrInti == -1)
356 {
358 << "procAndInterfaces:" << procAndInterfaces << abort(FatalError);
360 return nbrInti;
361}
362
363
364// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
365
366Foam::lduPrimitiveMesh::lduPrimitiveMesh
367(
368 const label nCells,
369 labelList& l,
370 labelList& u,
371 const label comm,
372 bool reuse
373)
374:
375 lduAddressing(nCells),
376 lowerAddr_(l, reuse),
377 upperAddr_(u, reuse),
378 comm_(comm)
379{
380 if (debug && lowerAddr_.size())
381 {
382 if (max(lowerAddr_) >= nCells || min(lowerAddr_) < 0)
383 {
384 FatalErrorInFunction << "Illegal lower addressing."
385 << " nCells:" << nCells
386 << " max(lower):" << max(lowerAddr_)
387 << " min(lower):" << min(lowerAddr_)
388 << exit(FatalError);
389 }
390 }
391 if (debug && upperAddr_.size())
392 {
393 if (max(upperAddr_) >= nCells || min(upperAddr_) < 0)
394 {
395 FatalErrorInFunction << "Illegal upper addressing."
396 << " nCells:" << nCells
397 << " max(upper):" << max(upperAddr_)
398 << " min(upper):" << min(upperAddr_)
399 << exit(FatalError);
400 }
401 }
402}
403
404
406(
407 lduInterfacePtrsList& interfaces,
408 const lduSchedule& ps
409)
410{
411 interfaces_ = interfaces;
412 patchSchedule_ = ps;
413
414 // Create interfaces
415 primitiveInterfaces_.setSize(interfaces_.size());
416 forAll(interfaces_, i)
417 {
418 if (interfaces_.set(i))
420 primitiveInterfaces_.set(i, &interfaces_[i]);
421 }
422 }
423}
424
425
426Foam::lduPrimitiveMesh::lduPrimitiveMesh
427(
428 const label nCells
430:
431 lduAddressing(nCells),
432 comm_(0)
433{}
434
435
436Foam::lduPrimitiveMesh::lduPrimitiveMesh
437(
438 const label nCells,
439 labelList& l,
440 labelList& u,
441 PtrList<const lduInterface>& primitiveInterfaces,
442 const lduSchedule& ps,
443 const label comm
444)
445:
446 lduAddressing(nCells),
447 lowerAddr_(l, true),
448 upperAddr_(u, true),
449 primitiveInterfaces_(),
450 patchSchedule_(ps),
451 comm_(comm)
452{
453 if (debug && lowerAddr_.size())
454 {
455 if (max(lowerAddr_) >= nCells || min(lowerAddr_) < 0)
456 {
457 FatalErrorInFunction << "Illegal lower addressing."
458 << " nCells:" << nCells
459 << " max(lower):" << max(lowerAddr_)
460 << " min(lower):" << min(lowerAddr_)
461 << exit(FatalError);
462 }
463 }
464 if (debug && upperAddr_.size())
465 {
466 if (max(upperAddr_) >= nCells || min(upperAddr_) < 0)
467 {
468 FatalErrorInFunction << "Illegal upper addressing."
469 << " nCells:" << nCells
470 << " max(upper):" << max(upperAddr_)
471 << " min(upper):" << min(upperAddr_)
472 << exit(FatalError);
473 }
474 }
475
476
477 primitiveInterfaces_.transfer(primitiveInterfaces);
478
479 // Create interfaces
480 interfaces_.setSize(primitiveInterfaces_.size());
481 forAll(primitiveInterfaces_, i)
482 {
483 if (primitiveInterfaces_.set(i))
485 interfaces_.set(i, &primitiveInterfaces_[i]);
486 }
487 }
488}
489
490
491Foam::lduPrimitiveMesh::lduPrimitiveMesh
492(
493 const label comm,
494 const labelList& procAgglomMap,
495
496 const labelList& procIDs,
497 const lduMesh& myMesh,
498 const PtrList<lduPrimitiveMesh>& otherMeshes,
499
500 labelList& cellOffsets,
501 labelList& faceOffsets,
503 labelListList& boundaryMap,
504 labelListListList& boundaryFaceMap
505)
506:
507 lduAddressing(myMesh.lduAddr().size() + totalSize(otherMeshes)),
508 comm_(comm)
509{
510 const label currentComm = myMesh.comm();
511
512 forAll(otherMeshes, i)
513 {
514 if (otherMeshes[i].comm() != currentComm)
515 {
517 << "Communicator " << otherMeshes[i].comm()
518 << " at index " << i
519 << " differs from that of predecessor "
520 << currentComm
521 << endl; //exit(FatalError);
522 }
523 }
524
525 const label nMeshes = otherMeshes.size()+1;
526
527 const label myAgglom = procAgglomMap[UPstream::myProcNo(currentComm)];
528 if (lduPrimitiveMesh::debug)
529 {
530 Pout<< "I am " << UPstream::myProcNo(currentComm)
531 << " agglomerating into " << myAgglom
532 << " as are " << findIndices(procAgglomMap, myAgglom)
533 << endl;
534 }
535
536 const lduInterfacePtrsList myInterfaces = myMesh.interfaces();
537
538 forAll(procIDs, i)
539 {
540 if (procAgglomMap[procIDs[i]] != procAgglomMap[procIDs[0]])
541 {
543 << "Processor " << procIDs[i]
544 << " agglomerates to " << procAgglomMap[procIDs[i]]
545 << " whereas other processors " << procIDs
546 << " agglomerate to "
547 << labelUIndList(procAgglomMap, procIDs)
548 << exit(FatalError);
549 }
550 }
551
552
553 // Cells get added in order.
554 cellOffsets.setSize(nMeshes+1);
555 cellOffsets[0] = 0;
556 for (label procMeshI = 0; procMeshI < nMeshes; ++procMeshI)
557 {
558 const lduMesh& procMesh = mesh(myMesh, otherMeshes, procMeshI);
559
560 cellOffsets[procMeshI+1] =
561 cellOffsets[procMeshI]
562 + procMesh.lduAddr().size();
563 }
564
565
566 // Faces initially get added in order, sorted later
567 labelList internalFaceOffsets(nMeshes+1);
568 internalFaceOffsets[0] = 0;
569 for (label procMeshI = 0; procMeshI < nMeshes; ++procMeshI)
570 {
571 const lduMesh& procMesh = mesh(myMesh, otherMeshes, procMeshI);
572
573 internalFaceOffsets[procMeshI+1] =
574 internalFaceOffsets[procMeshI]
575 + procMesh.lduAddr().lowerAddr().size();
576 }
577
578 // Count how faces get added. Proc interfaces inbetween get merged.
579
580 // Merged proc interfaces: map from two coarse processors back to
581 // - procMeshes
582 // - interface in procMesh
583 // (estimate size from number of patches of mesh0)
584 EdgeMap<labelPairList> mergedMap(2*myInterfaces.size());
585
586 // Unmerged proc interfaces: map from two coarse processors back to
587 // - procMeshes
588 // - interface in procMesh
589 EdgeMap<labelPairList> unmergedMap(mergedMap.size());
590
591 // (unmerged) global interfaces. These are present on all processors
592 // in the same order (and keep the order in the merged mesh)
593 List<DynamicList<label>> procToGlobal(nMeshes);
594
595
596 boundaryMap.setSize(nMeshes);
597 boundaryFaceMap.setSize(nMeshes);
598
599
600 labelList nCoupledFaces(nMeshes, Zero);
601
602 for (label procMeshI = 0; procMeshI < nMeshes; ++procMeshI)
603 {
605 mesh(myMesh, otherMeshes, procMeshI).interfaces();
606
607 // Initialise all boundaries as merged
608 boundaryMap[procMeshI].setSize(interfaces.size(), -1);
609 boundaryFaceMap[procMeshI].setSize(interfaces.size());
610
611 // Get sorted order of processors
612 forAll(interfaces, intI)
613 {
614 if (interfaces.set(intI))
615 {
616 const lduInterface& ldui = interfaces[intI];
617
619 {
621 {
623 << "At mesh from processor " << procIDs[procMeshI]
624 << " have interface " << intI
625 << " of unhandled type " << ldui.type()
626 << ". Adapt decomposition to avoid these"
627 << exit(FatalError);
628 }
629
630 const processorLduInterface& pldui =
632
633 label agglom0 = procAgglomMap[pldui.myProcNo()];
634 label agglom1 = procAgglomMap[pldui.neighbProcNo()];
635
636 const edge procEdge(agglom0, agglom1);
637
638 if (agglom0 != myAgglom && agglom1 != myAgglom)
639 {
641 << "At mesh from processor " << procIDs[procMeshI]
642 << " have interface " << intI
643 << " with myProcNo:" << pldui.myProcNo()
644 << " with neighbProcNo:" << pldui.neighbProcNo()
645 << exit(FatalError);
646 }
647 else if (agglom0 == myAgglom && agglom1 == myAgglom)
648 {
649 // Merged interface
650 if (debug)
651 {
652 Pout<< "merged proc interface: myProcNo:"
653 << pldui.myProcNo()
654 << " nbr:" << pldui.neighbProcNo()
655 << " size:" << ldui.faceCells().size()
656 << endl;
657 }
658
659 const label nbrProcMeshI =
660 procIDs.find(pldui.neighbProcNo());
661
662 if (procMeshI < nbrProcMeshI)
663 {
664 // I am 'master' since get lowest numbered cells
665 nCoupledFaces[procMeshI] += ldui.faceCells().size();
666 }
667
668 mergedMap(procEdge).append
669 (
670 labelPair(procMeshI, intI)
671 );
672 }
673 else
674 {
675 if (debug)
676 {
677 Pout<< "external proc interface: myProcNo:"
678 << pldui.myProcNo()
679 << " nbr:" << pldui.neighbProcNo()
680 << " size:" << ldui.faceCells().size()
681 << endl;
682 }
683
684 unmergedMap(procEdge).append
685 (
686 labelPair(procMeshI, intI)
687 );
688 }
689 }
690 else
691 {
692 // Still external (non proc) interface
693 procToGlobal[procMeshI].append(intI);
694 }
695 }
696 }
697 }
698
699
700 // Check that all processors have any global patches in the same order
701 if (debug)
702 {
703 const auto& global0 = procToGlobal[0];
704 for (label procMeshI = 1; procMeshI < nMeshes; ++procMeshI)
705 {
706 const auto& global = procToGlobal[procMeshI];
707 if (global != global0)
708 {
710 << "At mesh from processor " << procIDs[procMeshI]
711 << " have global interfaces " << global
712 << " which differ from those on processor "
713 << procIDs[procMeshI]
714 << " : " << global0
715 << exit(FatalError);
716 }
717 }
718 }
719
720
721 if (debug)
722 {
723 Pout<< "Global interfaces:" << endl;
724 const auto& global0 = procToGlobal[0];
725 for (const label intI : global0)
726 {
727 Pout<< " interfacei:" << intI
728 << " type:" << myInterfaces[intI].type()
729 << endl;
730
731 }
732 Pout<< endl;
733
734 Pout<< "Remaining interfaces:" << endl;
735 for (const auto& iter : unmergedMap.csorted())
736 {
737 Pout<< " agglom procEdge:" << iter.key() << endl;
738 const labelPairList& elems = iter.val();
739 forAll(elems, i)
740 {
741 label procMeshI = elems[i][0];
742 label interfacei = elems[i][1];
744 mesh(myMesh, otherMeshes, procMeshI).interfaces();
745
746 const processorLduInterface& pldui =
748 (
749 interfaces[interfacei]
750 );
751
752 Pout<< " proc:" << procIDs[procMeshI]
753 << " interfacei:" << interfacei
754 << " between:" << pldui.myProcNo()
755 << " and:" << pldui.neighbProcNo()
756 << " localsize:"
757 << interfaces[interfacei].faceCells().size()
758 << endl;
759 }
760 Pout<< endl;
761 }
762 Pout<< endl;
763
764 Pout<< "Merged interfaces:" << endl;
765 //forAllConstIters(mergedMap, iter)
766 for (const auto& iter : mergedMap.csorted())
767 {
768 Pout<< " agglom procEdge:" << iter.key() << endl;
769 const labelPairList& elems = iter.val();
770
771 forAll(elems, i)
772 {
773 label procMeshI = elems[i][0];
774 label interfacei = elems[i][1];
776 mesh(myMesh, otherMeshes, procMeshI).interfaces();
777 const processorLduInterface& pldui =
779 (
780 interfaces[interfacei]
781 );
782
783 Pout<< " proc:" << procIDs[procMeshI]
784 << " interfacei:" << interfacei
785 << " between:" << pldui.myProcNo()
786 << " and:" << pldui.neighbProcNo()
787 << " localsize:"
788 << interfaces[interfacei].faceCells().size()
789 << endl;
790 }
791 Pout<< endl;
792 }
793 Pout<< endl;
794 }
795
796
797 // Adapt faceOffsets for internal interfaces
798 faceOffsets.setSize(nMeshes+1);
799 faceOffsets[0] = 0;
800 faceMap.setSize(nMeshes);
801 for (label procMeshI = 0; procMeshI < nMeshes; ++procMeshI)
802 {
803 const lduMesh& procMesh = mesh(myMesh, otherMeshes, procMeshI);
804 label nInternal = procMesh.lduAddr().lowerAddr().size();
805
806 faceOffsets[procMeshI+1] =
807 faceOffsets[procMeshI]
808 + nInternal
809 + nCoupledFaces[procMeshI];
810
811 labelList& map = faceMap[procMeshI];
812 map.setSize(nInternal);
813 forAll(map, i)
814 {
815 map[i] = faceOffsets[procMeshI] + i;
816 }
817 }
818
819
820 // Combine upper and lower
821 lowerAddr_.setSize(faceOffsets.last(), -1);
822 upperAddr_.setSize(lowerAddr_.size(), -1);
823
824
825 // Old internal faces and resolved coupled interfaces
826 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
827
828 for (label procMeshI = 0; procMeshI < nMeshes; ++procMeshI)
829 {
830 const lduMesh& procMesh = mesh(myMesh, otherMeshes, procMeshI);
831
832 const labelUList& l = procMesh.lduAddr().lowerAddr();
833 const labelUList& u = procMesh.lduAddr().upperAddr();
834
835 // Add internal faces
836 label allFacei = faceOffsets[procMeshI];
837
838 forAll(l, facei)
839 {
840 lowerAddr_[allFacei] = cellOffsets[procMeshI]+l[facei];
841 upperAddr_[allFacei] = cellOffsets[procMeshI]+u[facei];
842 allFacei++;
843 }
844
845
846 // Add merged interfaces
847 const lduInterfacePtrsList interfaces = procMesh.interfaces();
848
849 forAll(interfaces, intI)
850 {
851 if (interfaces.set(intI))
852 {
853 const lduInterface& ldui = interfaces[intI];
854
856 {
857 const processorLduInterface& pldui =
859
860 // Look up corresponding interfaces
861 label myP = pldui.myProcNo();
862 label nbrP = pldui.neighbProcNo();
863 label nbrProcMeshI = procIDs.find(nbrP);
864
865 if (procMeshI < nbrProcMeshI)
866 {
867 // I am 'master' since my cell numbers will be lower
868 // since cells get added in procMeshI order.
869
870 const label agglom0 = procAgglomMap[myP];
871 const label agglom1 = procAgglomMap[nbrP];
872
873 const auto fnd =
874 mergedMap.cfind(edge(agglom0, agglom1));
875
876 if (fnd.good())
877 {
878 const labelPairList& elems = fnd();
879
880 const label nbrIntI = findConnectedInterface
881 (
882 myMesh,
883 otherMeshes,
884 elems,
885 nbrProcMeshI,
886 procIDs[procMeshI]
887 );
888
889 const lduInterfacePtrsList nbrInterfaces = mesh
890 (
891 myMesh,
892 otherMeshes,
893 nbrProcMeshI
894 ).interfaces();
895
896
897 const labelUList& faceCells =
898 ldui.faceCells();
899 const labelUList& nbrFaceCells =
900 nbrInterfaces[nbrIntI].faceCells();
901
902 if (faceCells.size() != nbrFaceCells.size())
903 {
905 << "faceCells:" << faceCells
906 << " nbrFaceCells:" << nbrFaceCells
907 << abort(FatalError);
908 }
909
910
911 labelList& bfMap =
912 boundaryFaceMap[procMeshI][intI];
913 labelList& nbrBfMap =
914 boundaryFaceMap[nbrProcMeshI][nbrIntI];
915
916 bfMap.setSize(faceCells.size());
917 nbrBfMap.setSize(faceCells.size());
918
919 forAll(faceCells, pfI)
920 {
921 lowerAddr_[allFacei] =
922 cellOffsets[procMeshI]+faceCells[pfI];
923 bfMap[pfI] = allFacei;
924 upperAddr_[allFacei] =
925 cellOffsets[nbrProcMeshI]+nbrFaceCells[pfI];
926 nbrBfMap[pfI] = (-allFacei-1);
927 allFacei++;
928 }
929 }
930 }
931 }
932 }
933 }
934 }
935
936
937 // Sort upper-tri order
938 {
939 labelList oldToNew
940 (
942 (
943 cellOffsets.last(), //nCells
944 lowerAddr_,
945 upperAddr_
946 )
947 );
948
949 forAll(faceMap, procMeshI)
950 {
951 labelList& map = faceMap[procMeshI];
952 forAll(map, i)
953 {
954 if (map[i] >= 0)
955 {
956 map[i] = oldToNew[map[i]];
957 }
958 else
959 {
960 label allFacei = -map[i]-1;
961 map[i] = -oldToNew[allFacei]-1;
962 }
963 }
964 }
965
966
967 inplaceReorder(oldToNew, lowerAddr_);
968 inplaceReorder(oldToNew, upperAddr_);
969
970 forAll(boundaryFaceMap, proci)
971 {
972 const labelList& bMap = boundaryMap[proci];
973 forAll(bMap, intI)
974 {
975 if (bMap[intI] == -1)
976 {
977 // Merged interface
978 labelList& bfMap = boundaryFaceMap[proci][intI];
979
980 forAll(bfMap, i)
981 {
982 if (bfMap[i] >= 0)
983 {
984 bfMap[i] = oldToNew[bfMap[i]];
985 }
986 else
987 {
988 label allFacei = -bfMap[i]-1;
989 bfMap[i] = (-oldToNew[allFacei]-1);
990 }
991 }
992 }
993 }
994 }
995 }
996
997
998 // Kept interfaces
999 // ~~~~~~~~~~~~~~~
1000
1001 interfaces_.setSize(unmergedMap.size() + procToGlobal[0].size());
1002 primitiveInterfaces_.setSize(interfaces_.size());
1003
1004 label allInterfacei = 0;
1005
1006
1007 // Global interfaces
1008 // ~~~~~~~~~~~~~~~~~
1009 // (e.g. cyclicAMI)
1010
1011 {
1012 const auto& global0 = procToGlobal[0];
1013
1014 for (const label interfacei : global0)
1015 {
1016 //Pout<< " interfacei:" << interfacei
1017 // << " type:" << interfaces[interfacei].type()
1018 // << endl;
1019
1020 // Just add all individual face-cells in processor order
1021
1022 // Count
1023 label n = 0;
1024 for (label procMeshI = 0; procMeshI < nMeshes; ++procMeshI)
1025 {
1026 const auto& procMesh = mesh(myMesh, otherMeshes, procMeshI);
1027 n += procMesh.interfaces()[interfacei].faceCells().size();
1028 }
1029
1030 // Size
1031 labelField allFaceCells(n);
1032 labelField allFaceRestrictAddressing(n);
1033 labelList faceOffsets(nMeshes+1, 0);
1034 lduInterfacePtrsList allProcInterfaces(nMeshes);
1035 n = 0;
1036
1037 // Fill
1038 for (label procMeshI = 0; procMeshI < nMeshes; ++procMeshI)
1039 {
1040 faceOffsets[procMeshI] = n;
1041
1042 const auto& procMesh = mesh(myMesh, otherMeshes, procMeshI);
1043 const lduInterfacePtrsList interfaces = procMesh.interfaces();
1044
1045 allProcInterfaces.set(procMeshI, &interfaces[interfacei]);
1046 boundaryMap[procMeshI][interfacei] = allInterfacei;
1047 labelList& bfMap = boundaryFaceMap[procMeshI][interfacei];
1048
1049 const labelUList& l = interfaces[interfacei].faceCells();
1050 bfMap.setSize(l.size());
1051
1052 forAll(l, facei)
1053 {
1054 allFaceCells[n] = cellOffsets[procMeshI]+l[facei];
1055 allFaceRestrictAddressing[n] = n;
1056 bfMap[facei] = n;
1057 n++;
1058 }
1059 }
1060
1061 // For convenience populate last element with size
1062 faceOffsets.last() = n;
1063
1064
1065 const auto& myFineInterface =
1066 refCast<const GAMGInterface>(myInterfaces[interfacei]);
1067
1068 autoPtr<GAMGInterface> ppPtr
1069 (
1070 myFineInterface.clone
1071 (
1072 allInterfacei,
1073 interfaces_,
1074 global0,
1075 allFaceCells,
1076 allFaceRestrictAddressing,
1077 faceOffsets,
1078 allProcInterfaces,
1079 comm_,
1080 myAgglom,
1081 procAgglomMap
1082 )
1083 );
1084
1085 primitiveInterfaces_.set
1086 (
1087 allInterfacei,
1088 ppPtr.ptr()
1089 );
1090
1091 interfaces_.set(allInterfacei, &primitiveInterfaces_[allInterfacei]);
1092
1093 if (debug)
1094 {
1095 Pout<< "Created " << interfaces_[allInterfacei].type()
1096 << " interface at " << allInterfacei
1097 << " comm:" << comm_
1098 << " myProcNo:" << myAgglom
1099 << " nFaces:" << allFaceCells.size()
1100 << endl;
1101 }
1102
1103 allInterfacei++;
1104 }
1105 }
1106
1107
1108 // Unmerged processor interfaces
1109 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1110
1111 //forAllConstIters(unmergedMap, iter)
1112 for (const auto& iter : unmergedMap.csorted())
1113 {
1114 const labelPairList& elems = iter.val();
1115
1116 // Sort processors in increasing order so both sides walk through in
1117 // same order.
1118 labelPairList procPairs(elems.size());
1119 forAll(elems, i)
1120 {
1121 const labelPair& elem = elems[i];
1122 label procMeshI = elem[0];
1123 label interfacei = elem[1];
1125 (
1126 myMesh,
1127 otherMeshes,
1128 procMeshI
1129 ).interfaces();
1130
1131 const processorLduInterface& pldui =
1133 (
1134 interfaces[interfacei]
1135 );
1136 label myProcNo = pldui.myProcNo();
1137 label nbrProcNo = pldui.neighbProcNo();
1138 procPairs[i] = labelPair
1139 (
1140 min(myProcNo, nbrProcNo),
1141 max(myProcNo, nbrProcNo)
1142 );
1143 }
1144
1145 labelList order(sortedOrder(procPairs));
1146
1147 // Count
1148 label n = 0;
1149
1150 forAll(order, i)
1151 {
1152 const labelPair& elem = elems[order[i]];
1153 label procMeshI = elem[0];
1154 label interfacei = elem[1];
1156 (
1157 myMesh,
1158 otherMeshes,
1159 procMeshI
1160 ).interfaces();
1161
1162 n += interfaces[interfacei].faceCells().size();
1163 }
1164
1165 // Size
1166 labelField allFaceCells(n);
1167 labelField allFaceRestrictAddressing(n);
1168 n = 0;
1169
1170 // Fill
1171 forAll(order, i)
1172 {
1173 const labelPair& elem = elems[order[i]];
1174 label procMeshI = elem[0];
1175 label interfacei = elem[1];
1177 (
1178 myMesh,
1179 otherMeshes,
1180 procMeshI
1181 ).interfaces();
1182
1183 boundaryMap[procMeshI][interfacei] = allInterfacei;
1184 labelList& bfMap = boundaryFaceMap[procMeshI][interfacei];
1185
1186 const labelUList& l = interfaces[interfacei].faceCells();
1187 bfMap.setSize(l.size());
1188
1189 forAll(l, facei)
1190 {
1191 allFaceCells[n] = cellOffsets[procMeshI]+l[facei];
1192 allFaceRestrictAddressing[n] = n;
1193 bfMap[facei] = n;
1194 n++;
1195 }
1196 }
1197
1198
1199 // Find out local and remote processor in new communicator
1200
1201 label neighbProcNo = -1;
1202
1203 // See what the two processors map onto
1204
1205 if (iter.key()[0] == myAgglom)
1206 {
1207 if (iter.key()[1] == myAgglom)
1208 {
1210 << "problem procEdge:" << iter.key()
1211 << exit(FatalError);
1212 }
1213
1214 neighbProcNo = iter.key()[1];
1215 }
1216 else
1217 {
1218 if (iter.key()[1] != myAgglom)
1219 {
1221 << "problem procEdge:" << iter.key()
1222 << exit(FatalError);
1223 }
1224
1225 neighbProcNo = iter.key()[0];
1226 }
1227
1228 primitiveInterfaces_.set
1229 (
1230 allInterfacei,
1231 new processorGAMGInterface
1232 (
1233 allInterfacei,
1234 interfaces_,
1235 allFaceCells,
1236 allFaceRestrictAddressing,
1237 comm_,
1238 myAgglom,
1239 neighbProcNo,
1240 tensorField(), // forwardT
1241 Pstream::msgType() // tag
1242 )
1243 );
1244 interfaces_.set(allInterfacei, &primitiveInterfaces_[allInterfacei]);
1245
1246 if (debug)
1247 {
1248 Pout<< "Created " << interfaces_[allInterfacei].type()
1249 << " interface at " << allInterfacei
1250 << " comm:" << comm_
1251 << " myProcNo:" << myAgglom
1252 << " neighbProcNo:" << neighbProcNo
1253 << " nFaces:" << allFaceCells.size()
1254 << endl;
1255 }
1256
1257
1258 allInterfacei++;
1259 }
1260
1261
1262 if (allInterfacei != interfaces_.size())
1263 {
1264 FatalErrorInFunction << "allInterfacei:" << allInterfacei
1265 << " interfaces_:" << interfaces_.size() << exit(FatalError);
1266 }
1267
1268
1269 if (debug)
1270 {
1271 Pout<< endl
1272 << "Created new lduPrimitiveMesh:" << nl
1273 << " cells:" << this->lduAddr().size() << nl
1274 << " internal face lower:"
1275 << this->lduAddr().lowerAddr().size() << nl
1276 << " internal faces upper:"
1277 << this->lduAddr().upperAddr().size()
1278 << endl;
1279 forAll(interfaces_, i)
1280 {
1281 if (interfaces_.set(i))
1282 {
1283 Pout<< " interface:" << i << " type:" << interfaces_[i].type()
1284 << nl
1285 << " faceCells:" << flatOutput(interfaces_[i].faceCells())
1286 << endl;
1287 }
1288 }
1289
1290
1291 Pout<< "Original input meshes:" << endl;
1292 forAll(boundaryMap, procMeshI)
1293 {
1294 const auto& procMesh = mesh(myMesh, otherMeshes, procMeshI);
1295 const lduInterfacePtrsList interfaces = procMesh.interfaces();
1296
1297 Pout<< " proc:" << procMeshI
1298 << " interfaces:" << interfaces.size() << endl;
1299 forAll(interfaces, inti)
1300 {
1301 if (interfaces.set(inti))
1302 {
1303 Pout<< " int:" << inti
1304 << " type:" << interfaces[inti].type()
1305 << " size:" << interfaces[inti].faceCells().size()
1306 << " maps to:" << boundaryMap[procMeshI][inti]
1307 << endl;
1308 }
1309 }
1310 }
1311 }
1312
1313
1314 patchSchedule_ = nonBlockingSchedule<processorGAMGInterface>(interfaces_);
1315
1316 if (debug)
1317 {
1318 checkUpperTriangular(cellOffsets.last(), lowerAddr_, upperAddr_);
1319 }
1320}
1321
1322
1323// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
1324
1326(
1327 const lduMesh& myMesh,
1328 const PtrList<lduPrimitiveMesh>& otherMeshes,
1329 const label meshI
1330)
1331{
1332 return (meshI == 0 ? myMesh : otherMeshes[meshI-1]);
1333}
1334
1335
1337(
1338 const label comm,
1339 const lduMesh& mesh,
1340 PtrList<lduPrimitiveMesh>& otherMeshes
1341)
1342{
1343 // Force calculation of schedule (since does parallel comms)
1344 (void)mesh.lduAddr().patchSchedule();
1345
1346 // Use PstreamBuffers
1347 PstreamBuffers pBufs(comm);
1348
1349 // Send to master
1350 if (!Pstream::master(comm))
1351 {
1352 const lduAddressing& addressing = mesh.lduAddr();
1353
1354 lduInterfacePtrsList interfaces(mesh.interfaces());
1355 boolList validInterface(interfaces.size());
1356 forAll(interfaces, intI)
1357 {
1358 validInterface[intI] = interfaces.set(intI);
1359 }
1360
1361 UOPstream toMaster(UPstream::masterNo(), pBufs);
1362
1363 toMaster
1364 << addressing.size()
1365 << addressing.lowerAddr()
1366 << addressing.upperAddr()
1367 << validInterface;
1368
1369 forAll(interfaces, intI)
1370 {
1371 if (interfaces.set(intI))
1372 {
1373 const GAMGInterface& interface = refCast<const GAMGInterface>
1374 (
1375 interfaces[intI]
1376 );
1377
1378 toMaster << interface.type();
1379 interface.write(toMaster);
1380 }
1381 }
1382 }
1383
1384 // Wait for finish
1385 pBufs.finishedGathers();
1386
1387 // Consume
1388 if (Pstream::master(comm))
1389 {
1390 const label nProcs = UPstream::nProcs(comm);
1391
1392 // Master.
1393 otherMeshes.setSize(nProcs-1);
1394
1395 for (const int proci : UPstream::subProcs(comm))
1396 {
1397 UIPstream fromProc(proci, pBufs);
1398
1399 const label nCells = readLabel(fromProc);
1400 labelList lowerAddr(fromProc);
1401 labelList upperAddr(fromProc);
1402 const boolList validInterface(fromProc);
1403
1404
1405 // Construct mesh without interfaces
1406 otherMeshes.set
1407 (
1408 proci-1,
1410 (
1411 nCells,
1412 lowerAddr,
1413 upperAddr,
1414 mesh.comm(),
1415 true // reuse
1416 )
1417 );
1418
1419 // Construct GAMGInterfaces
1420 lduInterfacePtrsList newInterfaces(validInterface.size());
1421 forAll(validInterface, intI)
1422 {
1423 if (validInterface[intI])
1424 {
1425 word coupleType(fromProc);
1426
1427 newInterfaces.set
1428 (
1429 intI,
1431 (
1432 coupleType,
1433 intI,
1434 otherMeshes[proci-1].rawInterfaces(),
1435 fromProc
1436 ).ptr()
1437 );
1438 }
1439 }
1440
1441 otherMeshes[proci-1].addInterfaces
1442 (
1443 newInterfaces,
1444 nonBlockingSchedule<processorGAMGInterface>
1445 (
1446 newInterfaces
1447 )
1448 );
1449 }
1450 }
1451}
1452
1453
1454// ************************************************************************* //
label n
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition DynamicList.H:68
void resize(const label len)
Alter addressable list size, allocating new space if required while recovering old content.
Map from edge (expressed as its endpoints) to value. Hashing (and ==) on an edge is symmetric.
Definition edgeHashes.H:59
Abstract base class for GAMG agglomerated interfaces.
static autoPtr< GAMGInterface > New(const label index, const lduInterfacePtrsList &coarseInterfaces, const lduInterface &fineInterface, const labelField &localRestrictAddressing, const labelField &neighbourRestrictAddressing, const label fineLevelIndex, const label coarseComm)
Return a pointer to a new interface created on freestore given.
const_iterator cfind(const Key &key) const
Find and return an const_iterator set at the hashed entry.
Definition HashTableI.H:113
label size() const noexcept
The number of elements in table.
Definition HashTable.H:358
UPtrList< const node_type > csorted() const
Const access to the hash-table contents in sorted order (sorted by keys).
Definition HashTable.C:181
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 append(const T &val)
Append an element at the end of the list.
Definition List.H:497
void setSize(label n)
Alias for resize().
Definition List.H:536
Buffers for inter-processor communications streams (UOPstream, UIPstream).
void finishedGathers(const bool wait=true)
Mark all sends to master as done.
A list of pointers to objects of type <T>, with allocation/deallocation management of the pointers....
Definition PtrList.H:67
const T * set(const label i) const
Return const pointer to element (can be nullptr), or nullptr for out-of-range access (ie,...
Definition PtrList.H:171
void setSize(const label n)
Same as resize().
Definition PtrList.H:357
Input inter-processor communications stream using MPI send/recv etc. - operating on external buffer.
Definition UIPstream.H:313
void size(const label n)
Older name for setAddressableSize.
Definition UList.H:118
T & last()
Access last element of the list, position [size()-1].
Definition UList.H:971
label find(const T &val) const
Find index of the first occurrence of the value.
Definition UList.C:160
Output inter-processor communications stream using MPI send/recv etc. - operating on external buffer.
Definition UOPstream.H:408
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
static label nRequests() noexcept
Number of outstanding requests (on the internal list of requests).
@ nonBlocking
"nonBlocking" (immediate) : (MPI_Isend, MPI_Irecv)
Definition UPstream.H:84
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 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 waitRequests()
Wait for all requests to finish.
Definition UPstream.H:2497
const T * set(const label i) const
Return const pointer to element (can be nullptr), or nullptr for out-of-range access (ie,...
Definition UPtrList.H:366
void setSize(const label n)
Alias for resize().
Definition UPtrList.H:842
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
T * ptr() noexcept
Same as release().
Definition autoPtr.H:248
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
Smooth ATC in cells next to a set of patches supplied by type.
Definition faceCells.H:55
virtual lduInterfacePtrsList interfaces() const
Return a list of pointers for each patch.
Definition fvMesh.C:724
virtual const lduAddressing & lduAddr() const
Return ldu addressing.
Definition fvMesh.C:707
virtual label comm() const
Return communicator used for parallel communication.
Definition fvMesh.H:415
Calculates a non-overlapping list of offsets based on an input size (eg, number of cells) from differ...
Definition globalIndex.H:77
label localStart(const label proci) const
Start of proci data.
The class contains the addressing required by the lduMatrix: upper, lower and losort.
void map(const UList< Type > &faceVals, List< Type > &vals) const
Helper to convert lower addressing & data into CSR format.
virtual const labelUList & upperAddr() const =0
Return upper addressing.
lduAddressing(const lduAddressing &)=delete
No copy construct.
virtual const labelUList & lowerAddr() const =0
Return lower addressing.
label size() const noexcept
Return number of equations.
An abstract base class for implicitly-coupled interfaces e.g. processor and cyclic patches.
virtual const labelUList & faceCells() const =0
Return faceCell addressing.
Abstract base class for meshes which provide LDU addressing for the construction of lduMatrix and LDU...
Definition lduMesh.H:54
virtual label comm() const =0
Return communicator used for parallel communication.
virtual const lduAddressing & lduAddr() const =0
Return ldu addressing.
virtual lduInterfacePtrsList interfaces() const =0
Return a list of pointers for each patch with only those pointing to interfaces being set.
Simplest concrete lduMesh that stores the addressing needed by lduMatrix.
virtual const labelUList & upperAddr() const
Return Upper addressing.
static void checkUpperTriangular(const label size, const labelUList &l, const labelUList &u)
Check if in upper-triangular ordering.
const lduInterfacePtrsList & rawInterfaces() const
Return a list of pointers for each patch.
static labelListList globalCellCells(const lduMesh &mesh, const globalIndex &globalNumbering)
Calculate global cell-cells.
void addInterfaces(lduInterfacePtrsList &interfaces, const lduSchedule &ps)
Add interfaces to a mesh constructed without.
static void gather(const label agglomComm, const lduMesh &mesh, PtrList< lduPrimitiveMesh > &otherMeshes)
Gather meshes from other processors using agglomComm.
PtrList< const lduInterface > & primitiveInterfaces()
Return a non-const list of primitive interfaces.
static labelList upperTriOrder(const label nCells, const labelUList &lower, const labelUList &upper)
Calculate upper-triangular order.
virtual label comm() const
Return communicator used for parallel communication.
static lduSchedule nonBlockingSchedule(const lduInterfacePtrsList &)
Get non-scheduled send/receive schedule.
static const lduMesh & mesh(const lduMesh &mesh0, const PtrList< lduPrimitiveMesh > &otherMeshes, const label meshI)
Select either mesh0 (meshI is 0) or otherMeshes[meshI-1].
virtual lduInterfacePtrsList interfaces() const
Return a list of pointers for each patch with only those pointing to interfaces being set.
virtual const lduAddressing & lduAddr() const
Return ldu addressing.
virtual const labelUList & lowerAddr() const
Return Lower addressing.
GAMG agglomerated processor interface.
An abstract base class for processor coupled interfaces.
virtual int neighbProcNo() const =0
Return neighbour processor number (rank in communicator).
virtual int myProcNo() const =0
Return processor number (rank in communicator).
A class for handling words, derived from Foam::string.
Definition word.H:66
#define defineTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information.
Definition className.H:142
dynamicFvMesh & mesh
Foam::PtrList< Foam::fvMesh > meshes(regionNames.size())
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition error.H:600
#define WarningInFunction
Report a warning using Foam::Warning.
const dimensionedScalar c1
First radiation constant: default SI units: [W/m2].
Namespace for handling debugging switches.
Definition debug.C:45
string upper(const std::string &s)
Return string copy transformed with std::toupper on each character.
string lower(const std::string &s)
Return string copy transformed with std::tolower on each character.
Namespace for OpenFOAM.
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
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
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition hashSets.C:40
List< labelPair > labelPairList
List of labelPair.
Definition labelPair.H:33
List< labelList > labelListList
List of labelList.
Definition labelList.H:38
List< label > labelList
A List of labels.
Definition List.H:62
UIndirectList< label > labelUIndList
UIndirectList of labels.
List< labelListList > labelListListList
List of labelListList.
Definition labelList.H:41
label readLabel(const char *buf)
Parse entire buffer as a label, skipping leading/trailing whitespace.
Definition label.H:63
UPtrList< const lduInterface > lduInterfacePtrsList
Store lists of lduInterface as a UPtrList.
List< lduScheduleEntry > lduSchedule
A List of lduSchedule entries.
Definition lduSchedule.H:46
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition Ostream.H:519
void inplaceReorder(const labelUList &oldToNew, ListType &input, const bool prune=false)
Inplace reorder the elements of a list.
const Type * isA(const U &obj)
Attempt dynamic_cast to Type.
Definition typeInfo.H:87
labelList sortedOrder(const UList< T > &input)
Return the (stable) sort order for the list.
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition hashSets.C:26
FlatOutput::OutputAdaptor< Container, Delimiters > flatOutput(const Container &obj, Delimiters delim)
Global flatOutput() function with specified output delimiters.
Definition FlatOutput.H:217
labelList identity(const label len, label start=0)
Return an identity map of the given length with (map[i] == i), works like std::iota() but returning a...
errorManip< error > abort(error &err)
Definition errorManip.H:139
Field< label > labelField
Specialisation of Field<T> for label.
Definition labelField.H:48
List< bool > boolList
A List of bools.
Definition List.H:60
static constexpr const zero Zero
Global zero (0).
Definition zero.H:127
Field< tensor > tensorField
Specialisation of Field<T> for tensor.
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
labelList findIndices(const ListType &input, typename ListType::const_reference val, label start=0)
Linear search to find all occurrences of given element.
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
interfaceProperties interface(alpha1, U, thermo->transportPropertiesDict())
#define forAll(list, i)
Loop across all elements in list.
Definition stdFoam.H:299