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-2023 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
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"
30 #include "GAMGInterface.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,
312  new lduPrimitiveMesh
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 thei 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]
398  }
399  }
400 
401  meshLevels_[fineLevelIndex].addInterfaces
402  (
403  coarseInterfaces,
404  lduPrimitiveMesh::nonBlockingSchedule<processorGAMGInterface>
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
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  (
509  CompactListList<label>::pack<labelList>
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
528  ConstPrecisionAdaptor<int, label, List>(localSizes).cref(),
529  ConstPrecisionAdaptor<int, label, List>(localStarts).cref(),
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  // Collect number of cells
563  labelList nFineCells;
565  (
566  comm,
567  procIDs,
568  restrictAddressing_[levelIndex].size(),
569  nFineCells,
570 
573  );
574  labelList fineOffsets(globalIndex::calcOffsets(nFineCells));
575 
576  // Combine and renumber nCoarseCells
577  labelList nCoarseCells;
579  (
580  comm,
581  procIDs,
582  nCells_[levelIndex],
583  nCoarseCells,
584 
587  );
588  labelList coarseOffsets(globalIndex::calcOffsets(nCoarseCells));
589 
590  // (cell)restrictAddressing
591  labelList procRestrictAddressing;
593  (
594  fineOffsets,
595  comm,
596  procIDs,
597  restrictAddressing_[levelIndex],
598  procRestrictAddressing,
599 
601  Pstream::commsTypes::nonBlocking //Pstream::commsTypes::scheduled
602  );
603 
604 
605  if (Pstream::myProcNo(comm) == procIDs[0])
606  {
607  nCells_[levelIndex] = coarseOffsets.last(); // ie, totalSize()
608 
609  // Renumber consecutively
610  for (label proci = 1; proci < procIDs.size(); ++proci)
611  {
612  SubList<label> procSlot
613  (
614  procRestrictAddressing,
615  fineOffsets[proci+1]-fineOffsets[proci],
616  fineOffsets[proci]
617  );
618 
619  // procSlot += coarseOffsets[proci];
620  forAll(procSlot, i)
621  {
622  procSlot[i] += coarseOffsets[proci];
623  }
624  }
625 
626  restrictAddressing_[levelIndex].transfer(procRestrictAddressing);
627  }
628 }
629 
630 
631 void Foam::GAMGAgglomeration::combineLevels(const label curLevel)
632 {
633  label prevLevel = curLevel - 1;
634 
635  // Set the previous level nCells to the current
636  nCells_[prevLevel] = nCells_[curLevel];
637  nFaces_[prevLevel] = nFaces_[curLevel];
638 
639  // Map the restrictAddressing from the coarser level into the previous
640  // finer level
641 
642  const labelList& curResAddr = restrictAddressing_[curLevel];
643  labelList& prevResAddr = restrictAddressing_[prevLevel];
644 
645  const labelList& curFaceResAddr = faceRestrictAddressing_[curLevel];
646  labelList& prevFaceResAddr = faceRestrictAddressing_[prevLevel];
647  const boolList& curFaceFlipMap = faceFlipMap_[curLevel];
648  boolList& prevFaceFlipMap = faceFlipMap_[prevLevel];
649 
650  forAll(prevFaceResAddr, i)
651  {
652  if (prevFaceResAddr[i] >= 0)
653  {
654  label fineFacei = prevFaceResAddr[i];
655  prevFaceResAddr[i] = curFaceResAddr[fineFacei];
656  prevFaceFlipMap[i] = curFaceFlipMap[fineFacei];
657  }
658  else
659  {
660  label fineFacei = -prevFaceResAddr[i] - 1;
661  prevFaceResAddr[i] = -curResAddr[fineFacei] - 1;
662  prevFaceFlipMap[i] = curFaceFlipMap[fineFacei];
663  }
664  }
665 
666  // Delete the restrictAddressing for the coarser level
667  faceRestrictAddressing_.set(curLevel, nullptr);
668  faceFlipMap_.set(curLevel, nullptr);
669 
670  forAll(prevResAddr, i)
671  {
672  prevResAddr[i] = curResAddr[prevResAddr[i]];
673  }
674 
675  const labelListList& curPatchFaceResAddr =
676  patchFaceRestrictAddressing_[curLevel];
677  labelListList& prevPatchFaceResAddr =
678  patchFaceRestrictAddressing_[prevLevel];
679 
680  forAll(prevPatchFaceResAddr, inti)
681  {
682  const labelList& curResAddr = curPatchFaceResAddr[inti];
683  labelList& prevResAddr = prevPatchFaceResAddr[inti];
684  forAll(prevResAddr, i)
685  {
686  label fineFacei = prevResAddr[i];
687  prevResAddr[i] = curResAddr[fineFacei];
688  }
689  }
690 
691  // Delete the restrictAddressing for the coarser level
692  restrictAddressing_.set(curLevel, nullptr);
693 
694  // Patch faces
695  nPatchFaces_[prevLevel] = nPatchFaces_[curLevel];
696 
697 
698 
699  // Adapt the restrict addressing for the patches
700  const lduInterfacePtrsList& curInterLevel =
701  meshLevels_[curLevel].rawInterfaces();
702  const lduInterfacePtrsList& prevInterLevel =
703  meshLevels_[prevLevel].rawInterfaces();
704 
705  forAll(prevInterLevel, inti)
706  {
707  if (prevInterLevel.set(inti))
708  {
709  GAMGInterface& prevInt = refCast<GAMGInterface>
710  (
711  const_cast<lduInterface&>
712  (
713  prevInterLevel[inti]
714  )
715  );
716  const GAMGInterface& curInt = refCast<const GAMGInterface>
717  (
718  curInterLevel[inti]
719  );
720  prevInt.combine(curInt);
721  }
722  }
723 
724  // Delete the matrix addressing and coefficients from the previous level
725  // and replace with the corresponding entry from the coarser level
726  meshLevels_.set(prevLevel, meshLevels_.set(curLevel, nullptr));
727 }
728 
729 
731 (
732  const label comm,
733  const labelList& procAgglomMap,
734  labelList& masterProcs,
735  List<label>& agglomProcIDs
736 )
737 {
738  // Determine the master processors
739  Map<label> agglomToMaster(procAgglomMap.size());
740 
741  forAll(procAgglomMap, proci)
742  {
743  const label coarsei = procAgglomMap[proci];
744 
745  auto iter = agglomToMaster.find(coarsei);
746  if (iter.good())
747  {
748  iter.val() = min(iter.val(), proci);
749  }
750  else
751  {
752  agglomToMaster.insert(coarsei, proci);
753  }
754  }
755 
756  masterProcs.setSize(agglomToMaster.size());
757  forAllConstIters(agglomToMaster, iter)
758  {
759  masterProcs[iter.key()] = iter.val();
760  }
761 
762 
763  // Collect all the processors in my agglomeration
764  label myProcID = Pstream::myProcNo(comm);
765  label myAgglom = procAgglomMap[myProcID];
766 
767  // Get all processors agglomerating to the same coarse
768  // processor
769  agglomProcIDs = findIndices(procAgglomMap, myAgglom);
770 
771  // Make sure the master is the first element.
772  const label index =
773  agglomProcIDs.find(agglomToMaster[myAgglom]);
774 
775  std::swap(agglomProcIDs[0], agglomProcIDs[index]);
776 }
777 
778 
779 // ************************************************************************* //
const labelList & faceRestrictAddressing(const label leveli) const
Return face restrict addressing of given level.
static labelList calcOffsets(const labelUList &counts, const bool checkOverflow=false)
Calculate offsets from a list of local sizes, with optional check for label overflow.
Definition: globalIndex.C:189
const labelList & nPatchFaces(const label leveli) const
Return number of coarse patch faces (before processor agglomeration)
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:116
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 boolList & faceFlipMap(const label leveli) const
Return face flip map of given level.
PtrList< labelListList > patchFaceRestrictAddressing_
Patch-local face restriction addressing array.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:598
const lduMesh & meshLevel(const label leveli) const
Return LDU mesh of given level.
std::enable_if< std::is_same< bool, TypeT >::value, bool >::type set(const label i, bool val=true)
A bitSet::set() method for a list of bool.
Definition: List.H:489
static label nRequests() noexcept
Number of outstanding requests (on the internal list of requests)
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
Abstract base class for meshes which provide LDU addressing for the construction of lduMatrix and LDU...
Definition: lduMesh.H:53
labelList findIndices(const ListType &input, typename ListType::const_reference val, label start=0)
Linear search to find all occurrences of given element.
static int & msgType() noexcept
Message tag of standard messages.
Definition: UPstream.H:1229
virtual label comm() const =0
Return communicator used for parallel communication.
static int myProcNo(const label communicator=worldComm)
Rank of this process in the communicator (starting from masterNo()). Can be negative if the process i...
Definition: UPstream.H:1074
void procAgglomerateLduAddressing(const label comm, const labelList &procAgglomMap, const labelList &procIDs, const label allMeshComm, const label levelIndex)
Collect and combine processor meshes into allMesh:
PtrList< labelList > faceRestrictAddressing_
Face restriction addressing array.
List< labelList > labelListList
List of labelList.
Definition: labelList.H:38
PtrList< labelList > nPatchFaces_
The number of (coarse) patch faces in each level.
virtual const labelUList & lowerAddr() const =0
Return lower addressing.
static void waitRequests()
Wait for all requests to finish.
Definition: UPstream.H:1538
static void scatter(const char *sendData, const UList< int > &sendCounts, const UList< int > &sendOffsets, char *recvData, int recvCount, const label communicator=worldComm)
Send variable length char data to all ranks.
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
void setSize(const label n)
Alias for resize()
Definition: List.H:316
"scheduled" : (MPI_Send, MPI_Recv)
PtrList< lduPrimitiveMesh > meshLevels_
Hierarchy of mesh addressing.
void clear()
Clear the list, i.e. set size to zero.
Definition: ListI.H:137
virtual const labelUList & upperAddr() const =0
Return upper addressing.
label size() const noexcept
The number of entries in the list.
Definition: UPtrListI.H:106
UPtrList< const lduInterface > lduInterfacePtrsList
Store lists of lduInterface as a UPtrList.
virtual const labelUList & patchAddr(const label patchNo) const =0
Return patch to internal addressing given patch number.
Simplest concrete lduMesh that stores the addressing needed by lduMatrix.
virtual const lduAddressing & lduAddr() const =0
Return ldu addressing.
labelList nCells_
The number of cells in each level.
List< labelListList > labelListListList
List of labelListList.
Definition: labelList.H:41
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:26
errorManip< error > abort(error &err)
Definition: errorManip.H:139
labelList nFaces_
The number of (coarse) faces in each level.
label find(const T &val) const
Find index of the first occurrence of the value.
Definition: UList.C:173
void agglomerateLduAddressing(const label fineLevelIndex)
Assemble coarse mesh addressing.
static void gather(const label agglomComm, const lduMesh &mesh, PtrList< lduPrimitiveMesh > &otherMeshes)
Gather meshes from other processors using agglomComm.
int debug
Static debugging option.
static void gatherValues(const label comm, const ProcIDsContainer &procIDs, const Type &localValue, List< Type > &allValues, const int tag=UPstream::msgType(), const UPstream::commsTypes=UPstream::commsTypes::nonBlocking)
Collect single values in processor order on master (== procIDs[0]).
void procAgglomerateRestrictAddressing(const label comm, const labelList &procIDs, const label levelIndex)
Collect and combine basic restriction addressing:
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.
"nonBlocking" : (MPI_Isend, MPI_Irecv)
The class contains the addressing required by the lduMatrix: upper, lower and losort.
PtrList< boolList > faceFlipMap_
Face flip: for faces mapped to internal faces stores whether.
#define forAllReverse(list, i)
Reverse loop across all elements in list.
Definition: stdFoam.H:437
static void gather(const labelUList &offsets, const label comm, const ProcIDsContainer &procIDs, const UList< Type > &fld, List< Type > &allFld, const int tag=UPstream::msgType(), const UPstream::commsTypes=UPstream::commsTypes::nonBlocking)
Collect data in processor order on master (== procIDs[0]).
List< label > labelList
A List of labels.
Definition: List.H:62
A class for managing temporary objects.
Definition: HashPtrTable.H:50
List< bool > boolList
A List of bools.
Definition: List.H:60
static void calculateRegionMaster(const label comm, const labelList &procAgglomMap, labelList &masterProcs, List< label > &agglomProcIDs)
Given fine to coarse processor map determine:
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
void combineLevels(const label curLevel)
Combine a level with the previous one.
forAllConstIters(mixture.phases(), phase)
Definition: pEqn.H:28
label size() const
Return number of equations.
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
FlatOutput::OutputAdaptor< Container, Delimiters > flatOutput(const Container &obj, Delimiters delim)
Global flatOutput() function with specified output delimiters.
Definition: FlatOutput.H:225
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:127