GAMGAgglomeration.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-2016 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 "lduMesh.H"
31 #include "lduMatrix.H"
32 #include "Time.H"
33 #include "GAMGInterface.H"
34 #include "GAMGProcAgglomeration.H"
35 #include "pairGAMGAgglomeration.H"
36 #include "IOmanip.H"
37 
38 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
39 
40 namespace Foam
41 {
42  defineTypeNameAndDebug(GAMGAgglomeration, 0);
43  defineRunTimeSelectionTable(GAMGAgglomeration, lduMesh);
44  defineRunTimeSelectionTable(GAMGAgglomeration, lduMatrix);
46 }
47 
48 
49 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
50 
52 (
53  const label nCreatedLevels,
54  const bool doProcessorAgglomerate
55 )
56 {
57  nCells_.setSize(nCreatedLevels, 0);
58  restrictAddressing_.setSize(nCreatedLevels);
59  nFaces_.setSize(nCreatedLevels, 0);
60  faceRestrictAddressing_.setSize(nCreatedLevels);
61  faceFlipMap_.setSize(nCreatedLevels);
62  nPatchFaces_.setSize(nCreatedLevels);
63  patchFaceRestrictAddressing_.setSize(nCreatedLevels);
64  meshLevels_.setSize(nCreatedLevels);
65 
66  // Have procCommunicator_ always, even if not procAgglomerating
67  procCommunicator_.setSize(nCreatedLevels + 1, -1);
68  if (doProcessorAgglomerate && processorAgglomerate())
69  {
70  procAgglomMap_.setSize(nCreatedLevels);
71  agglomProcIDs_.setSize(nCreatedLevels);
72  procAgglomCommunicator_.setSize(nCreatedLevels);
73  procCellOffsets_.setSize(nCreatedLevels);
74  procFaceMap_.setSize(nCreatedLevels);
75  procBoundaryMap_.setSize(nCreatedLevels);
76  procBoundaryFaceMap_.setSize(nCreatedLevels);
77 
78  procAgglomeratorPtr_().agglomerate();
79  }
80 }
81 
82 
84 {
85  Info<< "GAMGAgglomeration:" << nl
86  << " local agglomerator : " << type() << nl;
87  if (processorAgglomerate())
88  {
89  Info<< " processor agglomerator : "
90  << procAgglomeratorPtr_().type() << nl
91  << nl;
92  }
93 
94  Info<< setw(36) << "nCells"
95  << setw(20) << "nFaces/nCells"
96  << setw(20) << "nInterfaces"
97  << setw(20) << "nIntFaces/nCells"
98  << setw(12) << "profile"
99  << nl
100  << setw(8) << "Level"
101  << setw(8) << "nProcs"
102  << " "
103  << setw(8) << "avg"
104  << setw(8) << "max"
105  << " "
106  << setw(8) << "avg"
107  << setw(8) << "max"
108  << " "
109  << setw(8) << "avg"
110  << setw(8) << "max"
111  << " "
112  << setw(8) << "avg"
113  << setw(8) << "max"
114  //<< " "
115  << setw(12) << "avg"
116  << nl
117  << setw(8) << "-----"
118  << setw(8) << "------"
119  << " "
120  << setw(8) << "---"
121  << setw(8) << "---"
122  << " "
123  << setw(8) << "---"
124  << setw(8) << "---"
125  << " "
126  << setw(8) << "---"
127  << setw(8) << "---"
128  << " "
129  << setw(8) << "---"
130  << setw(8) << "---"
131  //<< " "
132  << setw(12) << "---"
133  //<< " "
134  << nl;
135 
136  const label maxSize = returnReduce(size(), maxOp<label>());
137 
138  for (label levelI = 0; levelI <= maxSize; levelI++)
139  {
140  label nProcs = 0;
141  label nCells = 0;
142  scalar faceCellRatio = 0;
143  label nInterfaces = 0;
144  label nIntFaces = 0;
145  scalar ratio = 0.0;
146  scalar profile = 0.0;
147 
148  if (hasMeshLevel(levelI))
149  {
150  nProcs = 1;
151 
152  const lduMesh& fineMesh = meshLevel(levelI);
153  nCells = fineMesh.lduAddr().size();
154  faceCellRatio =
155  scalar(fineMesh.lduAddr().lowerAddr().size())/nCells;
156 
157  const lduInterfacePtrsList interfaces =
158  fineMesh.interfaces();
159  forAll(interfaces, i)
160  {
161  if (interfaces.set(i))
162  {
163  nInterfaces++;
164  nIntFaces += interfaces[i].faceCells().size();
165  }
166  }
167  ratio = scalar(nIntFaces)/nCells;
168 
169  profile = fineMesh.lduAddr().band().second();
170  }
171 
172  label totNprocs = returnReduce(nProcs, sumOp<label>());
173 
174  label maxNCells = returnReduce(nCells, maxOp<label>());
175  label totNCells = returnReduce(nCells, sumOp<label>());
176 
177  scalar maxFaceCellRatio =
178  returnReduce(faceCellRatio, maxOp<scalar>());
179  scalar totFaceCellRatio =
180  returnReduce(faceCellRatio, sumOp<scalar>());
181 
182  label maxNInt = returnReduce(nInterfaces, maxOp<label>());
183  label totNInt = returnReduce(nInterfaces, sumOp<label>());
184 
185  scalar maxRatio = returnReduce(ratio, maxOp<scalar>());
186  scalar totRatio = returnReduce(ratio, sumOp<scalar>());
187 
188  scalar totProfile = returnReduce(profile, sumOp<scalar>());
189 
190  const int oldPrecision = Info.stream().precision(4);
191 
192  Info<< setw(8) << levelI
193  << setw(8) << totNprocs
194  << " "
195  << setw(8) << totNCells/totNprocs
196  << setw(8) << maxNCells
197  << " "
198  << setw(8) << totFaceCellRatio/totNprocs
199  << setw(8) << maxFaceCellRatio
200  << " "
201  << setw(8) << scalar(totNInt)/totNprocs
202  << setw(8) << maxNInt
203  << " "
204  << setw(8) << totRatio/totNprocs
205  << setw(8) << maxRatio
206  << setw(12) << totProfile/totNprocs
207  << nl;
208 
209  Info.stream().precision(oldPrecision);
210  }
211  Info<< endl;
212 }
213 
214 
216 (
217  const label nCellsInCoarsestLevel,
218  const label nFineCells,
219  const label nCoarseCells,
220  const label comm
221 ) const
222 {
223  const label nTotalCoarseCells =
224  returnReduce(nCoarseCells, sumOp<label>(), UPstream::msgType(), comm);
225  if (nTotalCoarseCells < Pstream::nProcs(comm)*nCellsInCoarsestLevel)
226  {
227  return false;
228  }
229  else
230  {
231  const label nTotalFineCells =
232  returnReduce(nFineCells, sumOp<label>(), UPstream::msgType(), comm);
233  return nTotalCoarseCells < nTotalFineCells;
234  }
235 }
236 
237 
238 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
239 
241 (
242  const lduMesh& mesh,
243  const dictionary& controlDict
244 )
245 :
246  MeshObject<lduMesh, Foam::GeometricMeshObject, GAMGAgglomeration>(mesh),
247 
248  maxLevels_(50),
249 
250  nCellsInCoarsestLevel_
251  (
252  controlDict.getOrDefault<label>("nCellsInCoarsestLevel", 10)
253  ),
254  meshInterfaces_(mesh.interfaces()),
255  procAgglomeratorPtr_
256  (
257  (
258  (UPstream::nProcs(mesh.comm()) > 1)
259  && controlDict.found("processorAgglomerator")
260  )
261  ? GAMGProcAgglomeration::New
262  (
263  controlDict.get<word>("processorAgglomerator"),
264  *this,
266  )
267  : autoPtr<GAMGProcAgglomeration>()
268  ),
269 
270  nCells_(maxLevels_),
271  restrictAddressing_(maxLevels_),
272  nFaces_(maxLevels_),
273  faceRestrictAddressing_(maxLevels_),
274  faceFlipMap_(maxLevels_),
275  nPatchFaces_(maxLevels_),
276  patchFaceRestrictAddressing_(maxLevels_),
277 
278  meshLevels_(maxLevels_)
279 {
280  // Limit the cells in the coarsest level based on the local number of
281  // cells. Note: 2 for pair-wise
284 
285  // Ensure all procs see the same nCellsInCoarsestLevel_
286  reduce(nCellsInCoarsestLevel_, minOp<label>());
287 
289  if (processorAgglomerate())
290  {
291  procAgglomMap_.setSize(maxLevels_);
292  agglomProcIDs_.setSize(maxLevels_);
294  procCellOffsets_.setSize(maxLevels_);
295  procFaceMap_.setSize(maxLevels_);
298  }
299 }
300 
301 
303 (
304  const lduMesh& mesh,
305  const dictionary& controlDict
306 )
307 {
308  const GAMGAgglomeration* agglomPtr =
309  mesh.thisDb().cfindObject<GAMGAgglomeration>
310  (
311  GAMGAgglomeration::typeName
312  );
313 
314  if (agglomPtr)
315  {
316  return *agglomPtr;
317  }
318 
319  {
320  const word agglomeratorType
321  (
322  controlDict.getOrDefault<word>("agglomerator", "faceAreaPair")
323  );
324 
325  mesh.thisDb().time().libs().open
326  (
327  controlDict,
328  "geometricGAMGAgglomerationLibs",
329  lduMeshConstructorTablePtr_
330  );
331 
332  auto* ctorPtr = lduMeshConstructorTable(agglomeratorType);
333 
334  if (!ctorPtr)
335  {
337  << "Unknown GAMGAgglomeration type "
338  << agglomeratorType << ".\n"
339  << "Valid matrix GAMGAgglomeration types :"
340  << lduMatrixConstructorTablePtr_->sortedToc() << endl
341  << "Valid geometric GAMGAgglomeration types :"
342  << lduMeshConstructorTablePtr_->sortedToc()
343  << exit(FatalError);
344  }
345 
346  auto agglomPtr(ctorPtr(mesh, controlDict));
347  if (debug)
348  {
349  agglomPtr().printLevels();
350  }
351  return store(agglomPtr.ptr());
352  }
353 }
354 
355 
357 (
358  const lduMatrix& matrix,
359  const dictionary& controlDict
360 )
361 {
362  const lduMesh& mesh = matrix.mesh();
363 
364  const GAMGAgglomeration* agglomPtr =
365  mesh.thisDb().cfindObject<GAMGAgglomeration>
366  (
367  GAMGAgglomeration::typeName
368  );
369 
370  if (agglomPtr)
371  {
372  return *agglomPtr;
373  }
374 
375  {
376  const word agglomeratorType
377  (
378  controlDict.getOrDefault<word>("agglomerator", "faceAreaPair")
379  );
380 
381  mesh.thisDb().time().libs().open
382  (
383  controlDict,
384  "algebraicGAMGAgglomerationLibs",
385  lduMatrixConstructorTablePtr_
386  );
387 
388  auto* ctorPtr = lduMatrixConstructorTable(agglomeratorType);
389 
390  if (!ctorPtr)
391  {
392  return New(mesh, controlDict);
393  }
394  else
395  {
396  auto agglomPtr(ctorPtr(matrix, controlDict));
397  if (debug)
398  {
399  agglomPtr().printLevels();
400  }
401  return store(agglomPtr.ptr());
402  }
403  }
404 }
405 
406 
408 (
409  const lduMesh& mesh,
410  const scalarField& cellVolumes,
411  const vectorField& faceAreas,
412  const dictionary& controlDict
413 )
414 {
415 
416  const GAMGAgglomeration* agglomPtr =
417  mesh.thisDb().cfindObject<GAMGAgglomeration>
418  (
419  GAMGAgglomeration::typeName
420  );
421 
422  if (agglomPtr)
423  {
424  return *agglomPtr;
425  }
426 
427  {
428  const word agglomeratorType
429  (
430  controlDict.getOrDefault<word>("agglomerator", "faceAreaPair")
431  );
432 
433  const_cast<Time&>(mesh.thisDb().time()).libs().open
434  (
435  controlDict,
436  "geometricGAMGAgglomerationLibs",
437  geometryConstructorTablePtr_
438  );
439 
440  auto* ctorPtr = geometryConstructorTable(agglomeratorType);
441 
442  if (!ctorPtr)
443  {
445  << "Unknown GAMGAgglomeration type "
446  << agglomeratorType << ".\n"
447  << "Valid geometric GAMGAgglomeration types :"
448  << geometryConstructorTablePtr_->sortedToc()
449  << exit(FatalError);
450  }
451 
452  auto agglomPtr
453  (
454  ctorPtr
455  (
456  mesh,
457  cellVolumes,
458  faceAreas,
460  )
461  );
462  if (debug)
463  {
464  agglomPtr().printLevels();
465  }
466  return store(agglomPtr.ptr());
467  }
468 }
469 
470 
471 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
472 
474 {}
475 
476 
477 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
478 
480 (
481  const label i
482 ) const
483 {
484  if (i == 0)
485  {
486  return mesh_;
487  }
488  else
489  {
490  return meshLevels_[i - 1];
491  }
492 }
493 
494 
495 bool Foam::GAMGAgglomeration::hasMeshLevel(const label i) const
496 {
497  if (i == 0)
498  {
499  return true;
500  }
501  else
502  {
503  return meshLevels_.set(i - 1);
504  }
505 }
506 
507 
509 (
510  const label i
511 ) const
512 {
513  if (i == 0)
514  {
515  return meshInterfaces_;
516  }
517  else
518  {
519  return meshLevels_[i - 1].rawInterfaces();
520  }
521 }
522 
523 
524 void Foam::GAMGAgglomeration::clearLevel(const label i)
525 {
526  if (hasMeshLevel(i))
527  {
528  meshLevels_.set(i - 1, nullptr);
529 
530  if (i < nCells_.size())
531  {
532  nCells_[i] = -555;
533  restrictAddressing_.set(i, nullptr);
534  nFaces_[i] = -666;
535  faceRestrictAddressing_.set(i, nullptr);
536  faceFlipMap_.set(i, nullptr);
537  nPatchFaces_.set(i, nullptr);
538  patchFaceRestrictAddressing_.set(i, nullptr);
539  }
540  }
541 }
542 
543 
545 (
546  const label leveli
547 ) const
548 {
549  return procAgglomMap_[leveli];
550 }
551 
552 
554 (
555  const label leveli
556 ) const
557 {
558  return agglomProcIDs_[leveli];
559 }
560 
562 bool Foam::GAMGAgglomeration::hasProcMesh(const label leveli) const
563 {
564  return procCommunicator_[leveli] != -1;
565 }
566 
568 Foam::label Foam::GAMGAgglomeration::procCommunicator(const label leveli) const
569 {
570  return procCommunicator_[leveli];
571 }
572 
573 
574 Foam::label Foam::GAMGAgglomeration::agglomCommunicator(const label leveli) const
575 {
576  return procAgglomCommunicator_[leveli];
577 }
578 
579 
581 (
582  const label leveli
583 ) const
584 {
585  return procCellOffsets_[leveli];
586 }
587 
588 
590 (
591  const label leveli
592 ) const
593 {
594  return procFaceMap_[leveli];
595 }
596 
597 
599 (
600  const label leveli
601 ) const
602 {
603  return procBoundaryMap_[leveli];
604 }
605 
606 
608 (
609  const label leveli
610 ) const
611 {
612  return procBoundaryFaceMap_[leveli];
613 }
614 
615 
617 (
618  labelList& newRestrict,
619  label& nNewCoarse,
620  const lduAddressing& fineAddressing,
621  const labelUList& restriction,
622  const label nCoarse
623 )
624 {
625  if (fineAddressing.size() != restriction.size())
626  {
628  << "nCells:" << fineAddressing.size()
629  << " agglom:" << restriction.size()
630  << abort(FatalError);
631  }
632 
633  // Seed (master) for every region
634  labelList master(identity(fineAddressing.size()));
635 
636  // Now loop and transport master through region
637  const labelUList& lower = fineAddressing.lowerAddr();
638  const labelUList& upper = fineAddressing.upperAddr();
639 
640  while (true)
641  {
642  label nChanged = 0;
643 
644  forAll(lower, facei)
645  {
646  const label own = lower[facei];
647  const label nei = upper[facei];
648 
649  if (restriction[own] == restriction[nei])
650  {
651  // coarse-mesh-internal face
652 
653  if (master[own] < master[nei])
654  {
655  master[nei] = master[own];
656  nChanged++;
657  }
658  else if (master[own] > master[nei])
659  {
660  master[own] = master[nei];
661  nChanged++;
662  }
663  }
664  }
665 
666  reduce(nChanged, sumOp<label>());
667 
668  if (nChanged == 0)
669  {
670  break;
671  }
672  }
673 
674 
675  // Count number of regions/masters per coarse cell
676  labelListList coarseToMasters(nCoarse);
677  nNewCoarse = 0;
678  forAll(restriction, celli)
679  {
680  labelList& masters = coarseToMasters[restriction[celli]];
681 
682  if (!masters.found(master[celli]))
683  {
684  masters.append(master[celli]);
685  nNewCoarse++;
686  }
687  }
688 
689  if (nNewCoarse > nCoarse)
690  {
691  //WarningInFunction
692  // << "Have " << nCoarse
693  // << " agglomerated cells but " << nNewCoarse
694  // << " disconnected regions" << endl;
695 
696  // Keep coarseToMasters[0] the original coarse, allocate new ones
697  // for the others
698  labelListList coarseToNewCoarse(coarseToMasters.size());
699 
700  nNewCoarse = nCoarse;
701 
702  forAll(coarseToMasters, coarseI)
703  {
704  const labelList& masters = coarseToMasters[coarseI];
705 
706  labelList& newCoarse = coarseToNewCoarse[coarseI];
707  newCoarse.setSize(masters.size());
708  newCoarse[0] = coarseI;
709  for (label i=1; i<newCoarse.size(); i++)
710  {
711  newCoarse[i] = nNewCoarse++;
712  }
713  }
714 
715  newRestrict.setSize(fineAddressing.size());
716  forAll(restriction, celli)
717  {
718  const label coarseI = restriction[celli];
719 
720  const label index = coarseToMasters[coarseI].find(master[celli]);
721  newRestrict[celli] = coarseToNewCoarse[coarseI][index];
722  }
723 
724  return false;
725  }
726 
727  return true;
728 }
729 
730 
731 // ************************************************************************* //
autoPtr< GAMGProcAgglomeration > procAgglomeratorPtr_
List< ReturnType > get(const UPtrList< T > &list, const AccessOp &aop)
List of values generated by applying the access operation to each list item.
PtrList< labelListList > procBoundaryMap_
Mapping from processor to procMeshLevel boundary.
bool hasProcMesh(const label fineLeveli) const
Check that level has combined mesh.
static bool checkRestriction(labelList &newRestrict, label &nNewCoarse, const lduAddressing &fineAddressing, const labelUList &restriction, const label nCoarse)
Given restriction determines if coarse cells are connected.
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:116
bool continueAgglomerating(const label nCellsInCoarsestLevel, const label nCells, const label nCoarseCells, const label comm) const
Check the need for further agglomeration.
PtrList< labelListList > procFaceMap_
Mapping from processor to procMeshLevel face.
dlLibraryTable & libs() const noexcept
Mutable access to the loaded dynamic libraries.
Definition: Time.H:730
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...
PtrList< labelListListList > procBoundaryFaceMap_
Mapping from processor to procMeshLevel boundary face.
GAMGAgglomeration(const GAMGAgglomeration &)=delete
No copy construct.
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:598
label agglomCommunicator(const label fineLeveli) const
Communicator for collecting contributions.
void append(const T &val)
Append an element at the end of the list.
Definition: List.H:517
const lduMesh & meshLevel(const label leveli) const
Return LDU mesh of given level.
PtrList< labelList > procCellOffsets_
Mapping from processor to procMeshLevel cells.
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:40
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
const labelListList & boundaryMap(const label fineLeveli) const
Mapping from processor to procMesh boundary.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
~GAMGAgglomeration()
Destructor.
Abstract base class for meshes which provide LDU addressing for the construction of lduMatrix and LDU...
Definition: lduMesh.H:53
tmp< DimensionedField< TypeR, GeoMesh > > New(const tmp< DimensionedField< TypeR, GeoMesh >> &tf1, const word &name, const dimensionSet &dimensions, const bool initCopy=false)
Global function forwards to reuseTmpDimensionedField::New.
static const GAMGAgglomeration & New(const lduMesh &mesh, const dictionary &controlDict)
Return the selected geometric agglomerator.
string upper(const std::string &s)
Return string copy transformed with std::toupper on each character.
Definition: stringOps.C:1187
static int & msgType() noexcept
Message tag of standard messages.
Definition: UPstream.H:1229
const Type * cfindObject(const word &name, const bool recursive=false) const
Return const pointer to the object of the given Type.
PtrList< labelList > faceRestrictAddressing_
Face restriction addressing array.
T returnReduce(const T &value, const BinaryOp &bop, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
Perform reduction on a copy, using specified binary operation.
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.
void clearLevel(const label leveli)
UList< label > labelUList
A UList of labels.
Definition: UList.H:78
PtrList< labelList > agglomProcIDs_
Per level the set of processors to agglomerate. Element 0 is.
virtual const objectRegistry & thisDb() const
Return the object registry - resolve conflict polyMesh/lduMesh.
Definition: fvMesh.H:376
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
label procCommunicator(const label fineLeveli) const
Communicator for current level or -1.
labelList procCommunicator_
Communicator for given level.
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
Definition: POSIX.C:799
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:1065
void setSize(const label n)
Alias for resize()
Definition: List.H:316
dynamicFvMesh & mesh
bool processorAgglomerate() const
Whether to agglomerate across processors.
PtrList< lduPrimitiveMesh > meshLevels_
Hierarchy of mesh addressing.
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...
Definition: labelLists.C:44
const lduMesh & mesh() const noexcept
Reference to the mesh.
Definition: MeshObject.H:157
virtual int precision() const override
Get precision of output field.
Definition: OSstream.C:334
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
const Time & time() const noexcept
Return time registry.
virtual const labelUList & upperAddr() const =0
Return upper addressing.
PtrList< UPstream::communicator > procAgglomCommunicator_
Communicator for collecting contributions. Note self-contained.
UPtrList< const lduInterface > lduInterfacePtrsList
Store lists of lduInterface as a UPtrList.
const labelList & agglomProcIDs(const label fineLeveli) const
Set of processors to agglomerate. Element 0 is the master processor. (local, same only on those proce...
void printLevels() const
Print level overview.
virtual const lduAddressing & lduAddr() const =0
Return ldu addressing.
labelList nCells_
The number of cells in each level.
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:26
runTime controlDict().readEntry("adjustTimeStep"
The central control dictionary, the contents of which are either taken directly from the FOAM_CONTROL...
Definition: debug.C:142
errorManip< error > abort(error &err)
Definition: errorManip.H:139
labelList nFaces_
The number of (coarse) faces in each level.
PtrList< labelField > restrictAddressing_
Cell restriction addressing array.
OSstream & stream(OSstream *alternative=nullptr)
Return OSstream for output operations. Use the alternative stream for serial-only output if it is a v...
Definition: messageStream.C:68
Istream and Ostream manipulators taking arguments.
defineRunTimeSelectionTable(reactionRateFlameArea, dictionary)
int debug
Static debugging option.
defineTypeNameAndDebug(combustionModel, 0)
const label maxLevels_
Max number of levels.
const labelList & cellOffsets(const label fineLeveli) const
Mapping from processor to procMesh cells.
string lower(const std::string &s)
Return string copy transformed with std::tolower on each character.
Definition: stringOps.C:1171
const labelListListList & boundaryFaceMap(const label fineLeveli) const
Mapping from processor to procMesh boundary face.
const labelList & procAgglomMap(const label fineLeveli) const
Mapping from processor to agglomerated processor (global, all processors have the same information)...
PtrList< labelList > procAgglomMap_
Per level, per processor the processor it agglomerates into.
const lduInterfacePtrsList & interfaceLevel(const label leveli) const
Return LDU interface addressing of given level.
void reduce(const List< UPstream::commsStruct > &comms, T &value, const BinaryOp &bop, const int tag, const label comm)
Reduce inplace (cf. MPI Allreduce) using specified communication schedule.
messageStream Info
Information stream (stdout output on master, null elsewhere)
Field< vector > vectorField
Specialisation of Field<T> for vector.
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.
Omanip< int > setw(const int i)
Definition: IOmanip.H:199
List< label > labelList
A List of labels.
Definition: List.H:62
bool open(bool verbose=true)
Open named, but unopened libraries. These names will normally have been added with the append() metho...
Geometric agglomerated algebraic multigrid agglomeration class.
bool found
bool hasMeshLevel(const label leveli) const
Do we have mesh for given level?
label nCellsInCoarsestLevel_
Number of cells in coarsest level.
void compactLevels(const label nCreatedLevels, const bool doProcessorAgglomerate)
Shrink the number of levels to that specified. Optionally do.
Namespace for OpenFOAM.
label size() const
Return number of equations.
const labelListList & faceMap(const label fineLeveli) const
Mapping from processor to procMesh face.