GAMGAgglomeration.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2026 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "GAMGAgglomeration.H"
27 #include "lduMesh.H"
28 #include "lduMatrix.H"
29 #include "Time.H"
30 #include "GAMGInterface.H"
31 #include "GAMGProcAgglomeration.H"
32 #include "pairGAMGAgglomeration.H"
33 #include "IOmanip.H"
34 
35 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
36 
37 namespace Foam
38 {
43 }
44 
45 
46 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
47 
49 {
50  nCells_.setSize(nCreatedLevels);
51  restrictAddressing_.setSize(nCreatedLevels);
52  nFaces_.setSize(nCreatedLevels);
53  faceRestrictAddressing_.setSize(nCreatedLevels);
54  faceFlipMap_.setSize(nCreatedLevels);
55  nPatchFaces_.setSize(nCreatedLevels);
56  patchFaceRestrictAddressing_.setSize(nCreatedLevels);
57  meshLevels_.setSize(nCreatedLevels);
58 
59  // Have procCommunicator_ always, even if not procAgglomerating
60  procCommunicator_.setSize(nCreatedLevels + 1);
62  {
63  procAgglomMap_.setSize(nCreatedLevels);
64  agglomProcIndices_.setSize(nCreatedLevels);
65  procCellOffsets_.setSize(nCreatedLevels);
66  procFaceMap_.setSize(nCreatedLevels);
67  procBoundaryMap_.setSize(nCreatedLevels);
68  procBoundaryFaceMap_.setSize(nCreatedLevels);
69 
70  procAgglomeratorPtr_().agglomerate();
71  }
72 
73  // Print a bit
74  if (processorAgglomerate() && debug)
75  {
76  Info<< "GAMGAgglomeration:" << nl
77  << " cell agglomerator : " << type() << nl;
79  {
80  Info<< " processor agglomerator : "
81  << procAgglomeratorPtr_().type() << nl
82  << nl;
83  }
84 
85  Info<< setw(36) << "nCells"
86  << setw(20) << "nFaces/nCells"
87  << setw(20) << "nInterfaces"
88  << setw(20) << "nIntFaces/nCells"
89  << setw(12) << "profile"
90  << nl
91  << setw(8) << "Level"
92  << setw(8) << "nProcs"
93  << " "
94  << setw(8) << "avg"
95  << setw(8) << "max"
96  << " "
97  << setw(8) << "avg"
98  << setw(8) << "max"
99  << " "
100  << setw(8) << "avg"
101  << setw(8) << "max"
102  << " "
103  << setw(8) << "avg"
104  << setw(8) << "max"
105  //<< " "
106  << setw(12) << "avg"
107  << nl
108  << setw(8) << "-----"
109  << setw(8) << "------"
110  << " "
111  << setw(8) << "---"
112  << setw(8) << "---"
113  << " "
114  << setw(8) << "---"
115  << setw(8) << "---"
116  << " "
117  << setw(8) << "---"
118  << setw(8) << "---"
119  << " "
120  << setw(8) << "---"
121  << setw(8) << "---"
122  //<< " "
123  << setw(12) << "---"
124  //<< " "
125  << nl;
126 
127  for (label levelI = 0; levelI <= size(); levelI++)
128  {
129  label nProcs = 0;
130  label nCells = 0;
131  scalar faceCellRatio = 0;
132  label nInterfaces = 0;
133  label nIntFaces = 0;
134  scalar ratio = 0.0;
135  scalar profile = 0.0;
136 
137  if (hasMeshLevel(levelI))
138  {
139  nProcs = 1;
140 
141  const lduMesh& fineMesh = meshLevel(levelI);
142  nCells = fineMesh.lduAddr().size();
143  faceCellRatio =
144  scalar(fineMesh.lduAddr().lowerAddr().size())/nCells;
145 
146  const lduInterfacePtrsList interfaces =
147  fineMesh.interfaces();
148  forAll(interfaces, i)
149  {
150  if (interfaces.set(i))
151  {
152  nInterfaces++;
153  nIntFaces += interfaces[i].faceCells().size();
154  }
155  }
156  ratio = scalar(nIntFaces)/nCells;
157 
158  profile = fineMesh.lduAddr().band().second();
159  }
160 
161  label totNprocs = returnReduce(nProcs, sumOp<label>());
162 
163  label maxNCells = returnReduce(nCells, maxOp<label>());
164  label totNCells = returnReduce(nCells, sumOp<label>());
165 
166  scalar maxFaceCellRatio =
167  returnReduce(faceCellRatio, maxOp<scalar>());
168  scalar totFaceCellRatio =
169  returnReduce(faceCellRatio, sumOp<scalar>());
170 
171  label maxNInt = returnReduce(nInterfaces, maxOp<label>());
172  label totNInt = returnReduce(nInterfaces, sumOp<label>());
173 
174  scalar maxRatio = returnReduce(ratio, maxOp<scalar>());
175  scalar totRatio = returnReduce(ratio, sumOp<scalar>());
176 
177  scalar totProfile = returnReduce(profile, sumOp<scalar>());
178 
179  int oldPrecision = Info().precision(4);
180 
181  Info<< setw(8) << levelI
182  << setw(8) << totNprocs
183  << " "
184  << setw(8) << totNCells/totNprocs
185  << setw(8) << maxNCells
186  << " "
187  << setw(8) << totFaceCellRatio/totNprocs
188  << setw(8) << maxFaceCellRatio
189  << " "
190  << setw(8) << scalar(totNInt)/totNprocs
191  << setw(8) << maxNInt
192  << " "
193  << setw(8) << totRatio/totNprocs
194  << setw(8) << maxRatio
195  << setw(12) << totProfile/totNprocs
196  << nl;
197 
198  Info().precision(oldPrecision);
199  }
200  Info<< endl;
201  }
202 }
203 
204 
206 (
207  const label nFineCells,
208  const label nCoarseCells
209 ) const
210 {
211  const label nTotalCoarseCells = returnReduce(nCoarseCells, sumOp<label>());
212 
213  if
214  (
215  nTotalCoarseCells <
216  (
217  processorAgglomerate()
218  ? minCellsPerProcessor_
219  : Pstream::nProcs()*minCellsPerProcessor_
220  )
221  )
222  {
223  return false;
224  }
225  else
226  {
227  const label nTotalFineCells = returnReduce(nFineCells, sumOp<label>());
228  return nTotalCoarseCells < nTotalFineCells;
229  }
230 }
231 
232 
233 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
234 
236 (
237  const lduMesh& mesh,
238  const dictionary& controlDict
239 )
240 :
242  <
243  lduMesh,
246  >(mesh),
247 
248  maxLevels_(50),
249 
250  minCellsPerProcessor_
251  (
252  controlDict.lookupOrDefaultBackwardsCompatible<label>
253  (
254  {"minCellsPerProcessor", "nCellsInCoarsestLevel"},
255  10
256  )
257  ),
258  meshInterfaces_(mesh.interfaces()),
259  procAgglomeratorPtr_
260  (
261  (
262  (UPstream::nProcs(mesh.comm()) > 1)
263  && controlDict.isDict("processorAgglomeration")
264  )
266  (
267  *this,
268  controlDict.subDict("processorAgglomeration")
269  )
271  ),
272 
273  nCells_(maxLevels_),
274  restrictAddressing_(maxLevels_),
275  nFaces_(maxLevels_),
276  faceRestrictAddressing_(maxLevels_),
277  faceFlipMap_(maxLevels_),
278  nPatchFaces_(maxLevels_),
279  patchFaceRestrictAddressing_(maxLevels_),
280 
281  meshLevels_(maxLevels_)
282 {
283  procCommunicator_.setSize(maxLevels_ + 1, -1);
284  if (processorAgglomerate())
285  {
286  procAgglomMap_.setSize(maxLevels_);
287  agglomProcIndices_.setSize(maxLevels_);
288  procCellOffsets_.setSize(maxLevels_);
289  procFaceMap_.setSize(maxLevels_);
290  procBoundaryMap_.setSize(maxLevels_);
291  procBoundaryFaceMap_.setSize(maxLevels_);
292  }
293 }
294 
295 
297 (
298  const lduMesh& mesh,
299  const dictionary& controlDict
300 )
301 {
302  if
303  (
305  (
307  )
308  )
309  {
310  const word agglomeratorType
311  (
312  controlDict.lookupOrDefault<word>("agglomerator", "faceAreaPair")
313  );
314 
315  libs.open
316  (
317  controlDict,
318  "geometricGAMGAgglomerationLibs",
319  lduMeshConstructorTablePtr_
320  );
321 
322  lduMeshConstructorTable::iterator cstrIter =
323  lduMeshConstructorTablePtr_->find(agglomeratorType);
324 
325  if (cstrIter == lduMeshConstructorTablePtr_->end())
326  {
328  << "Unknown GAMGAgglomeration type "
329  << agglomeratorType << ".\n"
330  << "Valid matrix GAMGAgglomeration types are :"
331  << lduMatrixConstructorTablePtr_->sortedToc() << endl
332  << "Valid geometric GAMGAgglomeration types are :"
333  << lduMeshConstructorTablePtr_->sortedToc()
334  << exit(FatalError);
335  }
336 
337  return store(cstrIter()(mesh, controlDict).ptr());
338  }
339  else
340  {
342  (
344  );
345  }
346 }
347 
348 
350 (
351  const lduMatrix& matrix,
352  const dictionary& controlDict
353 )
354 {
355  const lduMesh& mesh = matrix.mesh();
356 
357  if
358  (
360  (
362  )
363  )
364  {
365  const word agglomeratorType
366  (
367  controlDict.lookupOrDefault<word>("agglomerator", "faceAreaPair")
368  );
369 
370  libs.open
371  (
372  controlDict,
373  "algebraicGAMGAgglomerationLibs",
374  lduMatrixConstructorTablePtr_
375  );
376 
377  if
378  (
379  !lduMatrixConstructorTablePtr_
380  || !lduMatrixConstructorTablePtr_->found(agglomeratorType)
381  )
382  {
383  return New(mesh, controlDict);
384  }
385  else
386  {
387  lduMatrixConstructorTable::iterator cstrIter =
388  lduMatrixConstructorTablePtr_->find(agglomeratorType);
389 
390  return store(cstrIter()(matrix, controlDict).ptr());
391  }
392  }
393  else
394  {
396  (
398  );
399  }
400 }
401 
402 
404 (
405  const lduMesh& mesh,
406  const scalarField& cellVolumes,
407  const vectorField& faceAreas,
408  const dictionary& controlDict
409 )
410 {
411  const word agglomeratorType
412  (
413  controlDict.lookupOrDefault<word>("agglomerator", "faceAreaPair")
414  );
415 
416  libs.open
417  (
418  controlDict,
419  "geometricGAMGAgglomerationLibs",
420  geometryConstructorTablePtr_
421  );
422 
423  geometryConstructorTable::iterator cstrIter =
424  geometryConstructorTablePtr_->find(agglomeratorType);
425 
426  if (cstrIter == geometryConstructorTablePtr_->end())
427  {
429  << "Unknown GAMGAgglomeration type "
430  << agglomeratorType << ".\n"
431  << "Valid geometric GAMGAgglomeration types are :"
432  << geometryConstructorTablePtr_->sortedToc()
433  << exit(FatalError);
434  }
435 
437  (
438  cstrIter()
439  (
440  mesh,
441  cellVolumes,
442  faceAreas,
444  )
445  );
446 }
447 
448 
449 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
450 
452 {}
453 
454 
455 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
456 
458 (
459  const label i
460 ) const
461 {
462  if (i == 0)
463  {
464  return mesh();
465  }
466  else
467  {
468  return meshLevels_[i - 1];
469  }
470 }
471 
472 
474 {
475  if (i == 0)
476  {
477  return true;
478  }
479  else
480  {
481  return meshLevels_.set(i - 1);
482  }
483 }
484 
485 
487 (
488  const label i
489 ) const
490 {
491  if (i == 0)
492  {
493  return meshInterfaces_;
494  }
495  else
496  {
497  return meshLevels_[i - 1].rawInterfaces();
498  }
499 }
500 
501 
503 {
504  if (hasMeshLevel(i))
505  {
506  meshLevels_.set(i - 1, nullptr);
507 
508  if (i < nCells_.size())
509  {
510  nCells_[i] = -555;
511  restrictAddressing_.set(i, nullptr);
512  nFaces_[i] = -666;
513  faceRestrictAddressing_.set(i, nullptr);
514  faceFlipMap_.set(i, nullptr);
515  nPatchFaces_.set(i, nullptr);
516  patchFaceRestrictAddressing_.set(i, nullptr);
517  }
518  }
519 }
520 
521 
523 (
524  const label leveli
525 ) const
526 {
527  return procAgglomMap_[leveli];
528 }
529 
530 
532 (
533  const label leveli
534 ) const
535 {
536  return agglomProcIndices_[leveli];
537 }
538 
539 
541 {
542  return procCommunicator_[leveli] != -1;
543 }
544 
545 
547 {
548  return procCommunicator_[leveli];
549 }
550 
551 
553 (
554  const label leveli
555 ) const
556 {
557  return procCellOffsets_[leveli];
558 }
559 
560 
562 (
563  const label leveli
564 ) const
565 {
566  return procFaceMap_[leveli];
567 }
568 
569 
571 (
572  const label leveli
573 ) const
574 {
575  return procBoundaryMap_[leveli];
576 }
577 
578 
580 (
581  const label leveli
582 ) const
583 {
584  return procBoundaryFaceMap_[leveli];
585 }
586 
587 
589 (
590  labelList& newRestrict,
591  label& nNewCoarse,
592  const lduAddressing& fineAddressing,
593  const labelUList& restrict,
594  const label nCoarse
595 )
596 {
597  if (fineAddressing.size() != restrict.size())
598  {
600  << "nCells:" << fineAddressing.size()
601  << " agglom:" << restrict.size()
602  << abort(FatalError);
603  }
604 
605  // Seed (master) for every region
606  labelList master(identityMap(fineAddressing.size()));
607 
608  // Now loop and transport master through region
609  const labelUList& lower = fineAddressing.lowerAddr();
610  const labelUList& upper = fineAddressing.upperAddr();
611 
612  while (true)
613  {
614  label nChanged = 0;
615 
616  forAll(lower, facei)
617  {
618  label own = lower[facei];
619  label nei = upper[facei];
620 
621  if (restrict[own] == restrict[nei])
622  {
623  // coarse-mesh-internal face
624 
625  if (master[own] < master[nei])
626  {
627  master[nei] = master[own];
628  nChanged++;
629  }
630  else if (master[own] > master[nei])
631  {
632  master[own] = master[nei];
633  nChanged++;
634  }
635  }
636  }
637 
638  reduce(nChanged, sumOp<label>());
639 
640  if (nChanged == 0)
641  {
642  break;
643  }
644  }
645 
646 
647  // Count number of regions/masters per coarse cell
648  labelListList coarseToMasters(nCoarse);
649  nNewCoarse = 0;
650  forAll(restrict, celli)
651  {
652  labelList& masters = coarseToMasters[restrict[celli]];
653 
654  if (findIndex(masters, master[celli]) == -1)
655  {
656  masters.append(master[celli]);
657  nNewCoarse++;
658  }
659  }
660 
661  if (nNewCoarse > nCoarse)
662  {
663  // WarningInFunction
664  // << "Have " << nCoarse
665  // << " agglomerated cells but " << nNewCoarse
666  // << " disconnected regions" << endl;
667 
668  // Keep coarseToMasters[0] the original coarse, allocate new ones
669  // for the others
670  labelListList coarseToNewCoarse(coarseToMasters.size());
671 
672  nNewCoarse = nCoarse;
673 
674  forAll(coarseToMasters, coarseI)
675  {
676  const labelList& masters = coarseToMasters[coarseI];
677 
678  labelList& newCoarse = coarseToNewCoarse[coarseI];
679  newCoarse.setSize(masters.size());
680  newCoarse[0] = coarseI;
681  for (label i=1; i<newCoarse.size(); i++)
682  {
683  newCoarse[i] = nNewCoarse++;
684  }
685  }
686 
687  newRestrict.setSize(fineAddressing.size());
688  forAll(restrict, celli)
689  {
690  label coarseI = restrict[celli];
691 
692  label index = findIndex(coarseToMasters[coarseI], master[celli]);
693  newRestrict[celli] = coarseToNewCoarse[coarseI][index];
694  }
695 
696  return false;
697  }
698  else
699  {
700  return true;
701  }
702 }
703 
704 
705 // ************************************************************************* //
Istream and Ostream manipulators taking arguments.
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:449
MeshObject types:
Definition: MeshObjects.H:70
Templated abstract base-class for demand-driven mesh objects used to automate their allocation to the...
Geometric agglomerated algebraic multigrid agglomeration class.
bool processorAgglomerate() const
Whether to agglomerate across processors.
void clearLevel(const label leveli)
const labelListListList & boundaryFaceMap(const label fineLeveli) const
Mapping from processor to procMesh boundary face.
static const GAMGAgglomeration & New(const lduMesh &mesh, const dictionary &controlDict)
Return the selected geometric agglomerator.
PtrList< labelListList > patchFaceRestrictAddressing_
Patch-local face restriction addressing array.
PtrList< boolList > faceFlipMap_
Face flip: for faces mapped to internal faces stores whether.
PtrList< labelList > nPatchFaces_
The number of (coarse) patch faces in each level.
PtrList< labelList > agglomProcIndices_
Per level the set of processors to agglomerate. Element 0 is.
const labelList & procAgglomMap(const label fineLeveli) const
Mapping from processor to agglomerated processor (global, all.
autoPtr< GAMGProcAgglomeration > procAgglomeratorPtr_
void compactLevels(const label nCreatedLevels)
Shrink the number of levels to that specified.
labelList nFaces_
The number of (coarse) faces in each level.
PtrList< lduPrimitiveMesh > meshLevels_
Hierarchy of mesh addressing.
const labelList & cellOffsets(const label fineLeveli) const
Mapping from processor to procMesh cells.
bool continueAgglomerating(const label nCells, const label nCoarseCells) const
Check the need for further agglomeration.
labelList nCells_
The number of cells in each level.
bool hasProcMesh(const label fineLeveli) const
Check that level has combined mesh.
const labelListList & faceMap(const label fineLeveli) const
Mapping from processor to procMesh face.
GAMGAgglomeration(const lduMesh &mesh, const dictionary &controlDict)
Construct given mesh and controls.
labelList procCommunicator_
Communicator for given level.
PtrList< labelList > procAgglomMap_
Per level, per processor the processor it agglomerates into.
PtrList< labelListList > procBoundaryMap_
Mapping from processor to procMeshLevel boundary.
const labelListList & boundaryMap(const label fineLeveli) const
Mapping from processor to procMesh boundary.
const labelList & agglomProcIDs(const label fineLeveli) const
Set of processors to agglomerate. Element 0 is the.
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.
static bool checkRestriction(labelList &newRestrict, label &nNewCoarse, const lduAddressing &fineAddressing, const labelUList &restrict, const label nCoarse)
Given restriction determines if coarse cells are connected.
const lduInterfacePtrsList & interfaceLevel(const label leveli) const
Return LDU interface addressing of given level.
bool hasMeshLevel(const label leveli) const
Do we have mesh for given level?
label nCells(const label leveli) const
Return number of coarse cells (before processor agglomeration)
label procCommunicator(const label fineLeveli) const
Communicator for current level or -1.
const lduMesh & meshLevel(const label leveli) const
Return LDU mesh of given level.
PtrList< labelListListList > procBoundaryFaceMap_
Mapping from processor to procMeshLevel boundary face.
static autoPtr< GAMGProcAgglomeration > New(GAMGAgglomeration &agglom, const dictionary &dict)
Return the selected agglomerator.
void append(const T &)
Append an element at the end of the list.
Definition: ListI.H:178
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
void setSize(const label)
Reset size of List.
Definition: List.C:281
label size() const
Return the number of elements in the UList.
Definition: UListI.H:311
static label nProcs(const label communicator=0)
Number of processes in parallel run.
Definition: UPstream.H:411
bool set(const label) const
Is element set.
Definition: UPtrListI.H:87
label size() const
Return the number of elements in the UPtrList.
Definition: UPtrListI.H:29
An auto-pointer similar to the STL auto_ptr but with automatic casting to a reference to the type and...
Definition: autoPtr.H:51
A list of keywords followed by any number of values (e.g. words and numbers) or sub-dictionaries.
Definition: dictionary.H:162
bool open(const fileName &libName, const bool verbose=true)
Open the named library, optionally with warnings if problems occur.
virtual const objectRegistry & db() const
Return the object registry - resolve conflict polyMesh/lduMesh.
Definition: fvMesh.H:439
virtual label comm() const
Return communicator used for parallel communication.
Definition: fvMesh.H:484
virtual lduInterfacePtrsList interfaces() const
Return a list of pointers for each patch.
Definition: fvMesh.H:478
The class contains the addressing required by the lduMatrix: upper, lower and losort.
Tuple2< label, scalar > band() const
Calculate bandwidth and profile of addressing.
label size() const
Return number of equations.
virtual const labelUList & upperAddr() const =0
Return upper addressing.
virtual const labelUList & lowerAddr() const =0
Return lower addressing.
lduMatrix is a general matrix class in which the coefficients are stored as three arrays,...
Definition: lduMatrix.H:80
const lduMesh & mesh() const
Return the LDU mesh from which the addressing is obtained.
Definition: lduMatrix.H:544
Abstract base class for meshes which provide LDU addressing for the construction of lduMatrix and LDU...
Definition: lduMesh.H:60
virtual lduInterfacePtrsList interfaces() const =0
Return a list of pointers for each patch.
virtual const lduAddressing & lduAddr() const =0
Return ldu addressing.
const Type & lookupObject(const word &name) const
Lookup and return the object of the given Type and name.
bool foundObject(const word &name) const
Is the named Type in registry.
A class for handling words, derived from string.
Definition: word.H:63
Foam::fvMesh mesh(Foam::IOobject(regionName, runTime.name(), runTime, Foam::IOobject::MUST_READ), false)
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:334
Namespace for OpenFOAM.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
dlLibraryTable libs
Table of loaded dynamic libraries.
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:288
Omanip< int > setw(const int i)
Definition: IOmanip.H:199
String typeName(const std::type_info &info)
Return the un-mangled name given the standard type info.
errorManip< error > abort(error &err)
Definition: errorManip.H:131
messageStream Info
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
defineRunTimeSelectionTable(fvConstraint, dictionary)
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
label findIndex(const ListType &, typename ListType::const_reference, const label start=0)
Find first occurrence of given element and return index,.
error FatalError
labelList identityMap(const label len)
Create identity map (map[i] == i) of given length.
Definition: ListOps.C:104
defineTypeNameAndDebug(atmosphericBoundaryLayer, 0)
tmp< DimensionedField< TypeR, GeoMesh, Field > > New(const tmp< DimensionedField< TypeR, GeoMesh, Field >> &tdf1, const word &name, const dimensionSet &dimensions)
static const char nl
Definition: Ostream.H:297
runTime controlDict().lookup("adjustTimeStep") >> adjustTimeStep