Loading...
Searching...
No Matches
GAMGAgglomerateLduAddressing.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) 2019-2025 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 "GAMGAgglomeration.H"
32#include "cyclicLduInterface.H"
33#include "PrecisionAdaptor.H"
34
35// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
36
38(
39 const label fineLevelIndex
40)
41{
42 const lduMesh& fineMesh = meshLevel(fineLevelIndex);
43 const lduAddressing& fineMeshAddr = fineMesh.lduAddr();
44
45 const labelUList& upperAddr = fineMeshAddr.upperAddr();
46 const labelUList& lowerAddr = fineMeshAddr.lowerAddr();
47
48 const label nFineFaces = upperAddr.size();
49
50 // Get restriction map for current level
51 const labelField& restrictMap = restrictAddressing(fineLevelIndex);
52
53 if (min(restrictMap) == -1)
54 {
56 << "min(restrictMap) == -1" << exit(FatalError);
57 }
58
59 if (restrictMap.size() != fineMeshAddr.size())
60 {
62 << "restrict map does not correspond to fine level. " << endl
63 << " Sizes: restrictMap: " << restrictMap.size()
64 << " nEqns: " << fineMeshAddr.size()
65 << abort(FatalError);
66 }
67
68
69 // Get the number of coarse cells
70 const label nCoarseCells = nCells_[fineLevelIndex];
71
72 // Storage for coarse cell neighbours and coefficients
73
74 // Guess initial maximum number of neighbours in coarse cell
75 label maxNnbrs = 10;
76
77 // Number of faces for each coarse-cell
78 labelList cCellnFaces(nCoarseCells, Zero);
79
80 // Setup initial packed storage for coarse-cell faces
81 labelList cCellFaces(maxNnbrs*nCoarseCells);
82
83 // Create face-restriction addressing
84 faceRestrictAddressing_.set(fineLevelIndex, new labelList(nFineFaces));
85 labelList& faceRestrictAddr = faceRestrictAddressing_[fineLevelIndex];
86
87 // Initial neighbour array (not in upper-triangle order)
88 labelList initCoarseNeighb(nFineFaces);
89
90 // Counter for coarse faces
91 label& nCoarseFaces = nFaces_[fineLevelIndex];
92 nCoarseFaces = 0;
93
94 // Loop through all fine faces
95 forAll(upperAddr, fineFacei)
96 {
97 label rmUpperAddr = restrictMap[upperAddr[fineFacei]];
98 label rmLowerAddr = restrictMap[lowerAddr[fineFacei]];
99
100 if (rmUpperAddr == rmLowerAddr)
101 {
102 // For each fine face inside of a coarse cell keep the address
103 // of the cell corresponding to the face in the faceRestrictAddr
104 // as a negative index
105 faceRestrictAddr[fineFacei] = -(rmUpperAddr + 1);
106 }
107 else
108 {
109 // this face is a part of a coarse face
110
111 label cOwn = rmUpperAddr;
112 label cNei = rmLowerAddr;
113
114 // get coarse owner and neighbour
115 if (rmUpperAddr > rmLowerAddr)
116 {
117 cOwn = rmLowerAddr;
118 cNei = rmUpperAddr;
119 }
120
121 // check the neighbour to see if this face has already been found
122 label* ccFaces = &cCellFaces[maxNnbrs*cOwn];
123
124 bool nbrFound = false;
125 label& ccnFaces = cCellnFaces[cOwn];
126
127 for (int i=0; i<ccnFaces; i++)
128 {
129 if (initCoarseNeighb[ccFaces[i]] == cNei)
130 {
131 nbrFound = true;
132 faceRestrictAddr[fineFacei] = ccFaces[i];
133 break;
134 }
135 }
136
137 if (!nbrFound)
138 {
139 if (ccnFaces >= maxNnbrs)
140 {
141 label oldMaxNnbrs = maxNnbrs;
142 maxNnbrs *= 2;
143
144 cCellFaces.setSize(maxNnbrs*nCoarseCells);
145
146 forAllReverse(cCellnFaces, i)
147 {
148 label* oldCcNbrs = &cCellFaces[oldMaxNnbrs*i];
149 label* newCcNbrs = &cCellFaces[maxNnbrs*i];
150
151 for (int j=0; j<cCellnFaces[i]; j++)
152 {
153 newCcNbrs[j] = oldCcNbrs[j];
154 }
155 }
156
157 ccFaces = &cCellFaces[maxNnbrs*cOwn];
158 }
159
160 ccFaces[ccnFaces] = nCoarseFaces;
161 initCoarseNeighb[nCoarseFaces] = cNei;
162 faceRestrictAddr[fineFacei] = nCoarseFaces;
163 ccnFaces++;
164
165 // new coarse face created
166 nCoarseFaces++;
167 }
168 }
169 } // end for all fine faces
170
171
172 // Renumber into upper-triangular order
173
174 // All coarse owner-neighbour storage
175 labelList coarseOwner(nCoarseFaces);
176 labelList coarseNeighbour(nCoarseFaces);
177 labelList coarseFaceMap(nCoarseFaces);
178
179 label coarseFacei = 0;
180
181 forAll(cCellnFaces, cci)
182 {
183 label* cFaces = &cCellFaces[maxNnbrs*cci];
184 label ccnFaces = cCellnFaces[cci];
185
186 for (int i=0; i<ccnFaces; i++)
187 {
188 coarseOwner[coarseFacei] = cci;
189 coarseNeighbour[coarseFacei] = initCoarseNeighb[cFaces[i]];
190 coarseFaceMap[cFaces[i]] = coarseFacei;
191 coarseFacei++;
192 }
193 }
194
195 forAll(faceRestrictAddr, fineFacei)
196 {
197 if (faceRestrictAddr[fineFacei] >= 0)
198 {
199 faceRestrictAddr[fineFacei] =
200 coarseFaceMap[faceRestrictAddr[fineFacei]];
201 }
202 }
203
204
205 // Create face-flip status
206 faceFlipMap_.set(fineLevelIndex, new boolList(nFineFaces, false));
207 boolList& faceFlipMap = faceFlipMap_[fineLevelIndex];
208
209
210 forAll(faceRestrictAddr, fineFacei)
211 {
212 label coarseFacei = faceRestrictAddr[fineFacei];
213
214 if (coarseFacei >= 0)
215 {
216 // Maps to coarse face
217 label cOwn = coarseOwner[coarseFacei];
218 label cNei = coarseNeighbour[coarseFacei];
219
220 label rmUpperAddr = restrictMap[upperAddr[fineFacei]];
221 label rmLowerAddr = restrictMap[lowerAddr[fineFacei]];
222
223 if (cOwn == rmUpperAddr && cNei == rmLowerAddr)
224 {
225 faceFlipMap[fineFacei] = true;
226 }
227 else if (cOwn == rmLowerAddr && cNei == rmUpperAddr)
228 {
229 //faceFlipMap[fineFacei] = false;
230 }
231 else
232 {
234 << "problem."
235 << " fineFacei:" << fineFacei
236 << " rmUpperAddr:" << rmUpperAddr
237 << " rmLowerAddr:" << rmLowerAddr
238 << " coarseFacei:" << coarseFacei
239 << " cOwn:" << cOwn
240 << " cNei:" << cNei
241 << exit(FatalError);
242 }
243 }
244 }
245
246
247
248 // Clear the temporary storage for the coarse cell data
249 cCellnFaces.clear();
250 cCellFaces.clear();
251 initCoarseNeighb.clear();
252 coarseFaceMap.clear();
253
254
255 // Create coarse-level interfaces
256
257 // Get reference to fine-level interfaces
258 const lduInterfacePtrsList& fineInterfaces = interfaceLevel(fineLevelIndex);
259
260 nPatchFaces_.set
261 (
262 fineLevelIndex,
263 new labelList(fineInterfaces.size(), Zero)
264 );
265 labelList& nPatchFaces = nPatchFaces_[fineLevelIndex];
266
268 (
269 fineLevelIndex,
270 new labelListList(fineInterfaces.size())
271 );
272 labelListList& patchFineToCoarse =
273 patchFaceRestrictAddressing_[fineLevelIndex];
274
275
276 const label startOfRequests = UPstream::nRequests();
277
278 // Initialise transfer of restrict addressing on the interface
279 // The finest mesh uses patchAddr from the original lduAdressing.
280 // the coarser levels create their own adressing for faceCells
281 forAll(fineInterfaces, inti)
282 {
283 if (fineInterfaces.set(inti))
284 {
285 if (fineLevelIndex == 0)
286 {
287 fineInterfaces[inti].initInternalFieldTransfer
288 (
290 restrictMap,
291 fineMeshAddr.patchAddr(inti)
292 );
293 }
294 else
295 {
296 fineInterfaces[inti].initInternalFieldTransfer
297 (
299 restrictMap
300 );
301 }
302 }
303 }
304
305 UPstream::waitRequests(startOfRequests);
306
307
308 // Add the coarse level
309 meshLevels_.set
310 (
311 fineLevelIndex,
313 (
314 nCoarseCells,
315 coarseOwner,
316 coarseNeighbour,
317 fineMesh.comm(),
318 true
319 )
320 );
321
322 lduInterfacePtrsList coarseInterfaces(fineInterfaces.size());
323
324 forAll(fineInterfaces, inti)
325 {
326 if (fineInterfaces.set(inti))
327 {
328 tmp<labelField> restrictMapInternalField;
329
330 // The finest mesh uses patchAddr from the original lduAdressing.
331 // the coarser levels create their own adressing for faceCells
332 if (fineLevelIndex == 0)
333 {
334 restrictMapInternalField =
335 fineInterfaces[inti].interfaceInternalField
336 (
337 restrictMap,
338 fineMeshAddr.patchAddr(inti)
339 );
340 }
341 else
342 {
343 restrictMapInternalField =
344 fineInterfaces[inti].interfaceInternalField
345 (
346 restrictMap
347 );
348 }
349
350 tmp<labelField> nbrRestrictMapInternalField =
351 fineInterfaces[inti].internalFieldTransfer
352 (
354 restrictMap
355 );
356
357 coarseInterfaces.set
358 (
359 inti,
361 (
362 inti,
363 meshLevels_[fineLevelIndex].rawInterfaces(),
364 fineInterfaces[inti],
365 restrictMapInternalField(),
366 nbrRestrictMapInternalField(),
367 fineLevelIndex,
368 fineMesh.comm()
369 ).ptr()
370 );
371
372 /* Same as below:
373 coarseInterfaces.set
374 (
375 inti,
376 GAMGInterface::New
377 (
378 inti,
379 meshLevels_[fineLevelIndex].rawInterfaces(),
380 fineInterfaces[inti],
381 fineInterfaces[inti].interfaceInternalField(restrictMap),
382 fineInterfaces[inti].internalFieldTransfer
383 (
384 Pstream::commsTypes::nonBlocking,
385 restrictMap
386 ),
387 fineLevelIndex,
388 fineMesh.comm()
389 ).ptr()
390 );
391 */
392
393 nPatchFaces[inti] = coarseInterfaces[inti].faceCells().size();
394 patchFineToCoarse[inti] = refCast<const GAMGInterface>
395 (
396 coarseInterfaces[inti]
397 ).faceRestrictAddressing();
398 }
399 }
400
401 meshLevels_[fineLevelIndex].addInterfaces
402 (
403 coarseInterfaces,
405 (
406 coarseInterfaces
407 )
408 );
409
410
411 if (debug & 2)
412 {
413 const auto& coarseAddr = meshLevels_[fineLevelIndex].lduAddr();
414
415 Pout<< "GAMGAgglomeration :"
416 << " agglomerated level " << fineLevelIndex
417 << " from nCells:" << fineMeshAddr.size()
418 << " nFaces:" << upperAddr.size()
419 << " to nCells:" << nCoarseCells
420 << " nFaces:" << nCoarseFaces << nl
421 << " lower:" << flatOutput(coarseAddr.lowerAddr()) << nl
422 << " upper:" << flatOutput(coarseAddr.upperAddr()) << nl
423 << endl;
424 }
425}
426
427
429(
430 const label meshComm,
431 const labelList& procAgglomMap,
432 const labelList& procIDs,
433 const label allMeshComm,
434
435 const label levelIndex
436)
437{
438 // - Assemble all the procIDs in meshComm onto a single master
439 // (procIDs[0]). This constructs a new communicator ('comm') first.
440 // - The master communicates with neighbouring masters using
441 // allMeshComm
442
443 const lduMesh& myMesh = meshLevels_[levelIndex-1];
444 const label nOldInterfaces = myMesh.interfaces().size();
445
446 procAgglomMap_.set(levelIndex, new labelList(procAgglomMap));
447 agglomProcIDs_.set(levelIndex, new labelList(procIDs));
448 procCommunicator_[levelIndex] = allMeshComm;
449
450 procAgglomCommunicator_.set
451 (
452 levelIndex,
453 new UPstream::communicator
454 (
455 meshComm,
456 procIDs
457 )
458 );
459 const label comm = agglomCommunicator(levelIndex);
460
461 // These could only be set on the master procs but it is
462 // quite convenient to also have them on the slaves
463 procCellOffsets_.set(levelIndex, new labelList(0));
464 procFaceMap_.set(levelIndex, new labelListList(0));
465 procBoundaryMap_.set(levelIndex, new labelListList(0));
466 procBoundaryFaceMap_.set(levelIndex, new labelListListList(0));
467
468
469 // Collect meshes. Does no renumbering
470 PtrList<lduPrimitiveMesh> otherMeshes;
471 lduPrimitiveMesh::gather(comm, myMesh, otherMeshes);
472
473 if (Pstream::myProcNo(meshComm) == procIDs[0])
474 {
475 // Combine all addressing
476
477 labelList procFaceOffsets;
478 meshLevels_.set
479 (
480 levelIndex-1,
481 new lduPrimitiveMesh
482 (
483 allMeshComm,
484 procAgglomMap,
485
486 procIDs,
487 myMesh,
488 otherMeshes,
489
490 procCellOffsets_[levelIndex],
491 procFaceOffsets,
492 procFaceMap_[levelIndex],
493 procBoundaryMap_[levelIndex],
494 procBoundaryFaceMap_[levelIndex]
495 )
496 );
497 }
498
499
500 // Scatter the procBoundaryMap back to the originating processor
501 // so it knows which proc boundaries are to be kept. This is used
502 // so we only send over interfaceFields on kept processors (see
503 // GAMGSolver::procAgglomerateMatrix)
504 // TBD: using sub-communicator here (instead of explicit procIDs). Should
505 // use sub-communicators more in other places.
506 {
507 const CompactListList<label> data
508 (
510 (
511 procBoundaryMap_[levelIndex]
512 )
513 );
514 const labelList localSizes = data.localSizes();
515 const labelList& localStarts = data.offsets();
516
517 // Make space
518 procBoundaryMap_[levelIndex].setSize(procIDs.size());
519 labelList& bMap = procBoundaryMap_[levelIndex][Pstream::myProcNo(comm)];
520 bMap.setSize(nOldInterfaces);
521
522 // Scatter relevant section to originating processor
524 (
525 data.values().cdata(),
526
527 // Pass as List<int> for MPI
530
531 bMap.data(),
532 bMap.size(),
533 comm
534 );
535 }
536
537
538 // Combine restrict addressing
539 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~
540
541 procAgglomerateRestrictAddressing
542 (
543 meshComm,
544 procIDs,
545 levelIndex
546 );
547
548 if (Pstream::myProcNo(meshComm) != procIDs[0])
549 {
550 clearLevel(levelIndex);
551 }
552}
553
554
556(
557 const label comm,
558 const labelList& procIDs,
559 const label levelIndex
560)
561{
562 const bool master =
563 (
564 UPstream::myProcNo(comm) == (procIDs.empty() ? 0 : procIDs[0])
565 );
566
567 // Determine the fine/coarse sizes (offsets) for gathering
568 labelList fineOffsets;
569 labelList coarseOffsets;
570
571 {
572 List<labelPair> sizes = globalIndex::listGatherValues
573 (
574 comm,
575 procIDs,
577 (
578 // fine
579 restrictAddressing_[levelIndex].size(),
580 // coarse
581 nCells_[levelIndex]
582 ),
585 );
586
587 // Calculate offsets, as per globalIndex::calcOffsets()
588 // but extracting from the pair
589 if (master && !sizes.empty())
590 {
591 const label len = sizes.size();
592
593 fineOffsets.resize(len+1);
594 coarseOffsets.resize(len+1);
595
596 label fineCount = 0;
597 label coarseCount = 0;
598
599 for (label i = 0; i < len; ++i)
600 {
601 fineOffsets[i] = fineCount;
602 fineCount += sizes[i].first();
603
604 coarseOffsets[i] = coarseCount;
605 coarseCount += sizes[i].second();
606 }
607
608 fineOffsets[len] = fineCount;
609 coarseOffsets[len] = coarseCount;
610 }
611 }
612
613
614 // (cell)restrictAddressing
615 labelList procRestrictAddressing;
616 if (master)
617 {
618 // pre-size on master
619 procRestrictAddressing.resize(fineOffsets.back());
620 }
622 (
623 fineOffsets,
624 comm,
625 procIDs,
626 restrictAddressing_[levelIndex],
627 procRestrictAddressing,
630 );
631
632 if (master)
633 {
634 nCells_[levelIndex] = coarseOffsets.back(); // ie, totalSize()
635
636 // Renumber consecutively
637 for (label proci = 1; proci < procIDs.size(); ++proci)
638 {
639 SubList<label> procSlot
640 (
641 procRestrictAddressing,
642 fineOffsets[proci+1]-fineOffsets[proci],
643 fineOffsets[proci]
644 );
645
646 // procSlot += coarseOffsets[proci];
647 forAll(procSlot, i)
648 {
649 procSlot[i] += coarseOffsets[proci];
650 }
652
653 restrictAddressing_[levelIndex].transfer(procRestrictAddressing);
654 }
655}
656
657
658void Foam::GAMGAgglomeration::combineLevels(const label curLevel)
659{
660 label prevLevel = curLevel - 1;
661
662 // Set the previous level nCells to the current
663 nCells_[prevLevel] = nCells_[curLevel];
664 nFaces_[prevLevel] = nFaces_[curLevel];
665
666 // Map the restrictAddressing from the coarser level into the previous
667 // finer level
668
669 const labelList& curResAddr = restrictAddressing_[curLevel];
670 labelList& prevResAddr = restrictAddressing_[prevLevel];
671
672 const labelList& curFaceResAddr = faceRestrictAddressing_[curLevel];
673 labelList& prevFaceResAddr = faceRestrictAddressing_[prevLevel];
674 const boolList& curFaceFlipMap = faceFlipMap_[curLevel];
675 boolList& prevFaceFlipMap = faceFlipMap_[prevLevel];
676
677 forAll(prevFaceResAddr, i)
678 {
679 if (prevFaceResAddr[i] >= 0)
680 {
681 label fineFacei = prevFaceResAddr[i];
682 prevFaceResAddr[i] = curFaceResAddr[fineFacei];
683 prevFaceFlipMap[i] = curFaceFlipMap[fineFacei];
684 }
685 else
686 {
687 label fineFacei = -prevFaceResAddr[i] - 1;
688 prevFaceResAddr[i] = -curResAddr[fineFacei] - 1;
689 prevFaceFlipMap[i] = curFaceFlipMap[fineFacei];
690 }
691 }
692
693 // Delete the restrictAddressing for the coarser level
694 faceRestrictAddressing_.set(curLevel, nullptr);
695 faceFlipMap_.set(curLevel, nullptr);
696
697 forAll(prevResAddr, i)
698 {
699 prevResAddr[i] = curResAddr[prevResAddr[i]];
700 }
701
702 const labelListList& curPatchFaceResAddr =
703 patchFaceRestrictAddressing_[curLevel];
704 labelListList& prevPatchFaceResAddr =
705 patchFaceRestrictAddressing_[prevLevel];
706
707 forAll(prevPatchFaceResAddr, inti)
708 {
709 const labelList& curResAddr = curPatchFaceResAddr[inti];
710 labelList& prevResAddr = prevPatchFaceResAddr[inti];
711 forAll(prevResAddr, i)
712 {
713 label fineFacei = prevResAddr[i];
714 prevResAddr[i] = curResAddr[fineFacei];
715 }
716 }
717
718 // Delete the restrictAddressing for the coarser level
719 restrictAddressing_.set(curLevel, nullptr);
720
721 // Patch faces
722 nPatchFaces_[prevLevel] = nPatchFaces_[curLevel];
723
724
725
726 // Adapt the restrict addressing for the patches
727 const lduInterfacePtrsList& curInterLevel =
728 meshLevels_[curLevel].rawInterfaces();
729 const lduInterfacePtrsList& prevInterLevel =
730 meshLevels_[prevLevel].rawInterfaces();
731
732 forAll(prevInterLevel, inti)
733 {
734 if (prevInterLevel.set(inti))
735 {
737 (
738 const_cast<lduInterface&>
739 (
740 prevInterLevel[inti]
741 )
742 );
744 (
745 curInterLevel[inti]
746 );
747 prevInt.combine(curInt);
748 }
749 }
751 // Delete the matrix addressing and coefficients from the previous level
752 // and replace with the corresponding entry from the coarser level
753 meshLevels_.set(prevLevel, meshLevels_.set(curLevel, nullptr));
754}
755
756
758(
759 const label comm,
760 const labelList& procAgglomMap,
761 labelList& masterProcs,
762 List<label>& agglomProcIDs
763)
764{
765 // Determine the master processors
766 Map<label> agglomToMaster(procAgglomMap.size());
767
768 forAll(procAgglomMap, proci)
769 {
770 const label coarsei = procAgglomMap[proci];
771
772 auto iter = agglomToMaster.find(coarsei);
773 if (iter.good())
774 {
775 iter.val() = min(iter.val(), proci);
776 }
777 else
778 {
779 agglomToMaster.insert(coarsei, proci);
780 }
781 }
782
783 masterProcs.setSize(agglomToMaster.size());
784 forAllConstIters(agglomToMaster, iter)
785 {
786 masterProcs[iter.key()] = iter.val();
787 }
788
789
790 // Collect all the processors in my agglomeration
791 label myProcID = Pstream::myProcNo(comm);
792 label myAgglom = procAgglomMap[myProcID];
793
794 // Get all processors agglomerating to the same coarse
795 // processor
796 agglomProcIDs = findIndices(procAgglomMap, myAgglom);
797
798 // Make sure the master is the first element.
799 const label index =
800 agglomProcIDs.find(agglomToMaster[myAgglom]);
801
802 std::swap(agglomProcIDs[0], agglomProcIDs[index]);
803}
804
805
806// ************************************************************************* //
A packed storage of objects of type <T> using an offset table for access.
const labelList & offsets() const noexcept
Return the offset table (= size()+1).
const List< T > & values() const noexcept
Return the packed values.
static CompactListList< T > pack(const UList< SubListType > &lists, const bool checkOverflow=false)
Construct by packing together the list of lists.
labelList localSizes() const
The local row sizes.
A const Field/List wrapper with possible data conversion.
const labelList & nPatchFaces(const label leveli) const
Return number of coarse patch faces (before processor agglomeration).
void procAgglomerateRestrictAddressing(const label comm, const labelList &procIDs, const label levelIndex)
Collect and combine basic restriction addressing:
void clearLevel(const label leveli)
label agglomCommunicator(const label fineLeveli) const
Communicator for collecting contributions.
void agglomerateLduAddressing(const label fineLevelIndex)
Assemble coarse mesh addressing.
static void calculateRegionMaster(const label comm, const labelList &procAgglomMap, labelList &masterProcs, List< label > &agglomProcIDs)
Given fine to coarse processor map determine:
PtrList< labelListList > patchFaceRestrictAddressing_
Patch-local face restriction addressing array.
PtrList< boolList > faceFlipMap_
Face flip: for faces mapped to internal faces stores whether.
PtrList< UPstream::communicator > procAgglomCommunicator_
Communicator for collecting contributions. Note self-contained.
PtrList< labelList > nPatchFaces_
The number of (coarse) patch faces in each level.
void procAgglomerateLduAddressing(const label comm, const labelList &procAgglomMap, const labelList &procIDs, const label allMeshComm, const label levelIndex)
Collect and combine processor meshes into allMesh:
const labelList & procAgglomMap(const label fineLeveli) const
Mapping from processor to agglomerated processor (global, all processors have the same information)....
labelList nFaces_
The number of (coarse) faces in each level.
const boolList & faceFlipMap(const label leveli) const
Return face flip map of given level.
PtrList< lduPrimitiveMesh > meshLevels_
Hierarchy of mesh addressing.
labelList nCells_
The number of cells in each level.
labelList procCommunicator_
Communicator for given level.
PtrList< labelList > agglomProcIDs_
Per level the set of processors to agglomerate. Element 0 is.
PtrList< labelList > procAgglomMap_
Per level, per processor the processor it agglomerates into.
PtrList< labelListList > procBoundaryMap_
Mapping from processor to procMeshLevel boundary.
void combineLevels(const label curLevel)
Combine a level with the previous one.
const labelList & agglomProcIDs(const label fineLeveli) const
Set of processors to agglomerate. Element 0 is the master processor. (local, same only on those proce...
PtrList< labelList > procCellOffsets_
Mapping from processor to procMeshLevel cells.
PtrList< labelField > restrictAddressing_
Cell restriction addressing array.
PtrList< labelListList > procFaceMap_
Mapping from processor to procMeshLevel face.
PtrList< labelList > faceRestrictAddressing_
Face restriction addressing array.
const lduInterfacePtrsList & interfaceLevel(const label leveli) const
Return LDU interface addressing of given level.
const labelField & restrictAddressing(const label leveli) const
Return cell restrict addressing of given level.
const lduMesh & meshLevel(const label leveli) const
Return LDU mesh of given level.
PtrList< labelListListList > procBoundaryFaceMap_
Mapping from processor to procMeshLevel boundary face.
Abstract base class for GAMG agglomerated interfaces.
void combine(const GAMGInterface &)
Merge the next level with this level.
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.
bool insert(const Key &key, const T &obj)
Copy insert a new entry, not overwriting existing entries.
Definition HashTableI.H:152
iterator find(const Key &key)
Find and return an iterator set at the hashed entry.
Definition HashTableI.H:86
label size() const noexcept
The number of elements in table.
Definition HashTable.H:358
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
bool set(const label i, bool val=true)
A bitSet::set() method for a list of bool.
Definition List.H:469
void setSize(label n)
Alias for resize().
Definition List.H:536
void resize(const label len)
Adjust allocated size of list.
Definition ListI.H:153
void clear()
Clear the list, i.e. set size to zero.
Definition ListI.H:133
A HashTable to objects of type <T> with a label key.
Definition Map.H:54
A list of pointers to objects of type <T>, with allocation/deallocation management of the pointers....
Definition PtrList.H:67
A non-owning sub-view of a List (allocated or unallocated storage).
Definition SubList.H:61
T & first()
Access first element of the list, position [0].
Definition UList.H:957
bool empty() const noexcept
True if List is empty (ie, size() is zero).
Definition UList.H:701
T & back()
Access last element of the list, position [size()-1].
Definition UListI.H:253
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
Wrapper for internally indexed communicator label. Always invokes UPstream::allocateCommunicatorCompo...
Definition UPstream.H:2546
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).
@ scheduled
"scheduled" (MPI standard) : (MPI_Send, MPI_Recv)
Definition UPstream.H:83
@ 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 void mpiScatterv(const Type *sendData, const UList< int > &sendCounts, const UList< int > &sendOffsets, Type *recvData, int recvCount, const int communicator=UPstream::worldComm)
Send variable length data to all ranks.
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
label size() const noexcept
The number of entries in the list.
Definition UPtrListI.H:106
static void gather(const labelUList &offsets, const label comm, const ProcIDsContainer &procIDs, const UList< Type > &fld, UList< Type > &allFld, const int tag=UPstream::msgType(), UPstream::commsTypes commsType=UPstream::commsTypes::nonBlocking)
Collect data in processor order on master (== procIDs[0]).
static List< Type > listGatherValues(const label comm, const ProcIDsContainer &procIDs, const Type &localValue, const int tag=UPstream::msgType(), UPstream::commsTypes commsType=UPstream::commsTypes::nonBlocking)
Collect single values in processor order on master (== procIDs[0]).
The class contains the addressing required by the lduMatrix: upper, lower and losort.
virtual const labelUList & upperAddr() const =0
Return upper addressing.
virtual const labelUList & lowerAddr() const =0
Return lower addressing.
virtual const labelUList & patchAddr(const label patchNo) const =0
Return patch to internal addressing given patch number.
label size() const noexcept
Return number of equations.
An abstract base class for implicitly-coupled interfaces e.g. processor and cyclic patches.
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.
static void gather(const label agglomComm, const lduMesh &mesh, PtrList< lduPrimitiveMesh > &otherMeshes)
Gather meshes from other processors using agglomComm.
static lduSchedule nonBlockingSchedule(const lduInterfacePtrsList &)
Get non-scheduled send/receive schedule.
const T & cref() const
Return const reference to the object or to the contents of a (non-null) managed pointer.
Definition refPtrI.H:216
A class for managing temporary objects.
Definition tmp.H:75
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition error.H:600
Namespace for handling debugging switches.
Definition debug.C:45
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
List< labelList > labelListList
List of labelList.
Definition labelList.H:38
List< label > labelList
A List of labels.
Definition List.H:62
List< labelListList > labelListListList
List of labelListList.
Definition labelList.H:41
UPtrList< const lduInterface > lduInterfacePtrsList
Store lists of lduInterface as a UPtrList.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition Ostream.H:519
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
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
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
#define forAll(list, i)
Loop across all elements in list.
Definition stdFoam.H:299
#define forAllReverse(list, i)
Reverse loop across all elements in list.
Definition stdFoam.H:315
#define forAllConstIters(container, iter)
Iterate across all elements of the container object with const access.
Definition stdFoam.H:235