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-2023 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  agglomProcIDs_.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  }
74 
75  // Print a bit
76  if (processorAgglomerate() && debug)
77  {
78  Info<< "GAMGAgglomeration:" << nl
79  << " local agglomerator : " << type() << nl;
81  {
82  Info<< " processor agglomerator : "
83  << procAgglomeratorPtr_().type() << nl
84  << nl;
85  }
86 
87  Info<< setw(36) << "nCells"
88  << setw(20) << "nFaces/nCells"
89  << setw(20) << "nInterfaces"
90  << setw(20) << "nIntFaces/nCells"
91  << setw(12) << "profile"
92  << nl
93  << setw(8) << "Level"
94  << setw(8) << "nProcs"
95  << " "
96  << setw(8) << "avg"
97  << setw(8) << "max"
98  << " "
99  << setw(8) << "avg"
100  << setw(8) << "max"
101  << " "
102  << setw(8) << "avg"
103  << setw(8) << "max"
104  << " "
105  << setw(8) << "avg"
106  << setw(8) << "max"
107  //<< " "
108  << setw(12) << "avg"
109  << nl
110  << setw(8) << "-----"
111  << setw(8) << "------"
112  << " "
113  << setw(8) << "---"
114  << setw(8) << "---"
115  << " "
116  << setw(8) << "---"
117  << setw(8) << "---"
118  << " "
119  << setw(8) << "---"
120  << setw(8) << "---"
121  << " "
122  << setw(8) << "---"
123  << setw(8) << "---"
124  //<< " "
125  << setw(12) << "---"
126  //<< " "
127  << nl;
128 
129  for (label levelI = 0; levelI <= size(); levelI++)
130  {
131  label nProcs = 0;
132  label nCells = 0;
133  scalar faceCellRatio = 0;
134  label nInterfaces = 0;
135  label nIntFaces = 0;
136  scalar ratio = 0.0;
137  scalar profile = 0.0;
138 
139  if (hasMeshLevel(levelI))
140  {
141  nProcs = 1;
142 
143  const lduMesh& fineMesh = meshLevel(levelI);
144  nCells = fineMesh.lduAddr().size();
145  faceCellRatio =
146  scalar(fineMesh.lduAddr().lowerAddr().size())/nCells;
147 
148  const lduInterfacePtrsList interfaces =
149  fineMesh.interfaces();
150  forAll(interfaces, i)
151  {
152  if (interfaces.set(i))
153  {
154  nInterfaces++;
155  nIntFaces += interfaces[i].faceCells().size();
156  }
157  }
158  ratio = scalar(nIntFaces)/nCells;
159 
160  profile = fineMesh.lduAddr().band().second();
161  }
162 
163  label totNprocs = returnReduce(nProcs, sumOp<label>());
164 
165  label maxNCells = returnReduce(nCells, maxOp<label>());
166  label totNCells = returnReduce(nCells, sumOp<label>());
167 
168  scalar maxFaceCellRatio =
169  returnReduce(faceCellRatio, maxOp<scalar>());
170  scalar totFaceCellRatio =
171  returnReduce(faceCellRatio, sumOp<scalar>());
172 
173  label maxNInt = returnReduce(nInterfaces, maxOp<label>());
174  label totNInt = returnReduce(nInterfaces, sumOp<label>());
175 
176  scalar maxRatio = returnReduce(ratio, maxOp<scalar>());
177  scalar totRatio = returnReduce(ratio, sumOp<scalar>());
178 
179  scalar totProfile = returnReduce(profile, sumOp<scalar>());
180 
181  int oldPrecision = Info().precision(4);
182 
183  Info<< setw(8) << levelI
184  << setw(8) << totNprocs
185  << " "
186  << setw(8) << totNCells/totNprocs
187  << setw(8) << maxNCells
188  << " "
189  << setw(8) << totFaceCellRatio/totNprocs
190  << setw(8) << maxFaceCellRatio
191  << " "
192  << setw(8) << scalar(totNInt)/totNprocs
193  << setw(8) << maxNInt
194  << " "
195  << setw(8) << totRatio/totNprocs
196  << setw(8) << maxRatio
197  << setw(12) << totProfile/totNprocs
198  << nl;
199 
200  Info().precision(oldPrecision);
201  }
202  Info<< endl;
203  }
204 }
205 
206 
208 (
209  const label nFineCells,
210  const label nCoarseCells
211 ) const
212 {
213  const label nTotalCoarseCells = returnReduce(nCoarseCells, sumOp<label>());
214  if (nTotalCoarseCells < Pstream::nProcs()*nCellsInCoarsestLevel_)
215  {
216  return false;
217  }
218  else
219  {
220  const label nTotalFineCells = returnReduce(nFineCells, sumOp<label>());
221  return nTotalCoarseCells < nTotalFineCells;
222  }
223 }
224 
225 
226 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
227 
229 (
230  const lduMesh& mesh,
231  const dictionary& controlDict
232 )
233 :
235  <
236  lduMesh,
239  >(mesh),
240 
241  maxLevels_(50),
242 
243  nCellsInCoarsestLevel_
244  (
245  controlDict.lookupOrDefault<label>("nCellsInCoarsestLevel", 10)
246  ),
247  meshInterfaces_(mesh.interfaces()),
248  procAgglomeratorPtr_
249  (
250  (
251  (UPstream::nProcs(mesh.comm()) > 1)
252  && controlDict.found("processorAgglomerator")
253  )
255  (
256  controlDict.lookup("processorAgglomerator"),
257  *this,
259  )
260  : autoPtr<GAMGProcAgglomeration>(nullptr)
261  ),
262 
263  nCells_(maxLevels_),
264  restrictAddressing_(maxLevels_),
265  nFaces_(maxLevels_),
266  faceRestrictAddressing_(maxLevels_),
267  faceFlipMap_(maxLevels_),
268  nPatchFaces_(maxLevels_),
269  patchFaceRestrictAddressing_(maxLevels_),
270 
271  meshLevels_(maxLevels_)
272 {
274  if (processorAgglomerate())
275  {
276  procAgglomMap_.setSize(maxLevels_);
277  agglomProcIDs_.setSize(maxLevels_);
278  procCellOffsets_.setSize(maxLevels_);
279  procFaceMap_.setSize(maxLevels_);
280  procBoundaryMap_.setSize(maxLevels_);
282  }
283 }
284 
285 
287 (
288  const lduMesh& mesh,
289  const dictionary& controlDict
290 )
291 {
292  if
293  (
295  (
296  GAMGAgglomeration::typeName
297  )
298  )
299  {
300  const word agglomeratorType
301  (
302  controlDict.lookupOrDefault<word>("agglomerator", "faceAreaPair")
303  );
304 
305  libs.open
306  (
307  controlDict,
308  "geometricGAMGAgglomerationLibs",
309  lduMeshConstructorTablePtr_
310  );
311 
312  lduMeshConstructorTable::iterator cstrIter =
313  lduMeshConstructorTablePtr_->find(agglomeratorType);
314 
315  if (cstrIter == lduMeshConstructorTablePtr_->end())
316  {
318  << "Unknown GAMGAgglomeration type "
319  << agglomeratorType << ".\n"
320  << "Valid matrix GAMGAgglomeration types are :"
321  << lduMatrixConstructorTablePtr_->sortedToc() << endl
322  << "Valid geometric GAMGAgglomeration types are :"
323  << lduMeshConstructorTablePtr_->sortedToc()
324  << exit(FatalError);
325  }
326 
327  return store(cstrIter()(mesh, controlDict).ptr());
328  }
329  else
330  {
331  return mesh.thisDb().lookupObject<GAMGAgglomeration>
332  (
333  GAMGAgglomeration::typeName
334  );
335  }
336 }
337 
338 
340 (
341  const lduMatrix& matrix,
342  const dictionary& controlDict
343 )
344 {
345  const lduMesh& mesh = matrix.mesh();
346 
347  if
348  (
350  (
351  GAMGAgglomeration::typeName
352  )
353  )
354  {
355  const word agglomeratorType
356  (
357  controlDict.lookupOrDefault<word>("agglomerator", "faceAreaPair")
358  );
359 
360  libs.open
361  (
362  controlDict,
363  "algebraicGAMGAgglomerationLibs",
364  lduMatrixConstructorTablePtr_
365  );
366 
367  if
368  (
369  !lduMatrixConstructorTablePtr_
370  || !lduMatrixConstructorTablePtr_->found(agglomeratorType)
371  )
372  {
373  return New(mesh, controlDict);
374  }
375  else
376  {
377  lduMatrixConstructorTable::iterator cstrIter =
378  lduMatrixConstructorTablePtr_->find(agglomeratorType);
379 
380  return store(cstrIter()(matrix, controlDict).ptr());
381  }
382  }
383  else
384  {
385  return mesh.thisDb().lookupObject<GAMGAgglomeration>
386  (
387  GAMGAgglomeration::typeName
388  );
389  }
390 }
391 
392 
394 (
395  const lduMesh& mesh,
396  const scalarField& cellVolumes,
397  const vectorField& faceAreas,
398  const dictionary& controlDict
399 )
400 {
401  const word agglomeratorType
402  (
403  controlDict.lookupOrDefault<word>("agglomerator", "faceAreaPair")
404  );
405 
406  libs.open
407  (
408  controlDict,
409  "geometricGAMGAgglomerationLibs",
410  geometryConstructorTablePtr_
411  );
412 
413  geometryConstructorTable::iterator cstrIter =
414  geometryConstructorTablePtr_->find(agglomeratorType);
415 
416  if (cstrIter == geometryConstructorTablePtr_->end())
417  {
419  << "Unknown GAMGAgglomeration type "
420  << agglomeratorType << ".\n"
421  << "Valid geometric GAMGAgglomeration types are :"
422  << geometryConstructorTablePtr_->sortedToc()
423  << exit(FatalError);
424  }
425 
427  (
428  cstrIter()
429  (
430  mesh,
431  cellVolumes,
432  faceAreas,
434  )
435  );
436 }
437 
438 
439 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
440 
442 {}
443 
444 
445 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
446 
448 (
449  const label i
450 ) const
451 {
452  if (i == 0)
453  {
454  return mesh();
455  }
456  else
457  {
458  return meshLevels_[i - 1];
459  }
460 }
461 
462 
464 {
465  if (i == 0)
466  {
467  return true;
468  }
469  else
470  {
471  return meshLevels_.set(i - 1);
472  }
473 }
474 
475 
477 (
478  const label i
479 ) const
480 {
481  if (i == 0)
482  {
483  return meshInterfaces_;
484  }
485  else
486  {
487  return meshLevels_[i - 1].rawInterfaces();
488  }
489 }
490 
491 
493 {
494  if (hasMeshLevel(i))
495  {
496  meshLevels_.set(i - 1, nullptr);
497 
498  if (i < nCells_.size())
499  {
500  nCells_[i] = -555;
501  restrictAddressing_.set(i, nullptr);
502  nFaces_[i] = -666;
503  faceRestrictAddressing_.set(i, nullptr);
504  faceFlipMap_.set(i, nullptr);
505  nPatchFaces_.set(i, nullptr);
506  patchFaceRestrictAddressing_.set(i, nullptr);
507  }
508  }
509 }
510 
511 
513 (
514  const label leveli
515 ) const
516 {
517  return procAgglomMap_[leveli];
518 }
519 
520 
522 (
523  const label leveli
524 ) const
525 {
526  return agglomProcIDs_[leveli];
527 }
528 
529 
531 {
532  return procCommunicator_[leveli] != -1;
533 }
534 
535 
537 {
538  return procCommunicator_[leveli];
539 }
540 
541 
543 (
544  const label leveli
545 ) const
546 {
547  return procCellOffsets_[leveli];
548 }
549 
550 
552 (
553  const label leveli
554 ) const
555 {
556  return procFaceMap_[leveli];
557 }
558 
559 
561 (
562  const label leveli
563 ) const
564 {
565  return procBoundaryMap_[leveli];
566 }
567 
568 
570 (
571  const label leveli
572 ) const
573 {
574  return procBoundaryFaceMap_[leveli];
575 }
576 
577 
579 (
580  labelList& newRestrict,
581  label& nNewCoarse,
582  const lduAddressing& fineAddressing,
583  const labelUList& restrict,
584  const label nCoarse
585 )
586 {
587  if (fineAddressing.size() != restrict.size())
588  {
590  << "nCells:" << fineAddressing.size()
591  << " agglom:" << restrict.size()
592  << abort(FatalError);
593  }
594 
595  // Seed (master) for every region
596  labelList master(identityMap(fineAddressing.size()));
597 
598  // Now loop and transport master through region
599  const labelUList& lower = fineAddressing.lowerAddr();
600  const labelUList& upper = fineAddressing.upperAddr();
601 
602  while (true)
603  {
604  label nChanged = 0;
605 
606  forAll(lower, facei)
607  {
608  label own = lower[facei];
609  label nei = upper[facei];
610 
611  if (restrict[own] == restrict[nei])
612  {
613  // coarse-mesh-internal face
614 
615  if (master[own] < master[nei])
616  {
617  master[nei] = master[own];
618  nChanged++;
619  }
620  else if (master[own] > master[nei])
621  {
622  master[own] = master[nei];
623  nChanged++;
624  }
625  }
626  }
627 
628  reduce(nChanged, sumOp<label>());
629 
630  if (nChanged == 0)
631  {
632  break;
633  }
634  }
635 
636 
637  // Count number of regions/masters per coarse cell
638  labelListList coarseToMasters(nCoarse);
639  nNewCoarse = 0;
640  forAll(restrict, celli)
641  {
642  labelList& masters = coarseToMasters[restrict[celli]];
643 
644  if (findIndex(masters, master[celli]) == -1)
645  {
646  masters.append(master[celli]);
647  nNewCoarse++;
648  }
649  }
650 
651  if (nNewCoarse > nCoarse)
652  {
653  // WarningInFunction
654  // << "Have " << nCoarse
655  // << " agglomerated cells but " << nNewCoarse
656  // << " disconnected regions" << endl;
657 
658  // Keep coarseToMasters[0] the original coarse, allocate new ones
659  // for the others
660  labelListList coarseToNewCoarse(coarseToMasters.size());
661 
662  nNewCoarse = nCoarse;
663 
664  forAll(coarseToMasters, coarseI)
665  {
666  const labelList& masters = coarseToMasters[coarseI];
667 
668  labelList& newCoarse = coarseToNewCoarse[coarseI];
669  newCoarse.setSize(masters.size());
670  newCoarse[0] = coarseI;
671  for (label i=1; i<newCoarse.size(); i++)
672  {
673  newCoarse[i] = nNewCoarse++;
674  }
675  }
676 
677  newRestrict.setSize(fineAddressing.size());
678  forAll(restrict, celli)
679  {
680  label coarseI = restrict[celli];
681 
682  label index = findIndex(coarseToMasters[coarseI], master[celli]);
683  newRestrict[celli] = coarseToNewCoarse[coarseI][index];
684  }
685 
686  return false;
687  }
688  else
689  {
690  return true;
691  }
692 }
693 
694 
695 // ************************************************************************* //
Istream and Ostream manipulators taking arguments.
bool found
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
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.
const label maxLevels_
Max number of levels.
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 > 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.
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.
Processor agglomeration of GAMGAgglomerations.
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
Inter-processor communications stream.
Definition: UPstream.H:59
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:78
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 keyword definitions, which are a keyword followed by any number of values (e....
Definition: dictionary.H:160
bool open(const fileName &libName, const bool verbose=true)
Open the named library, optionally with warnings if problems occur.
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 const objectRegistry & thisDb() const
Return the object registry.
Definition: lduMesh.C:40
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:62
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:306
Namespace for OpenFOAM.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
dlLibraryTable libs
Table of loaded dynamic libraries.
defineRunTimeSelectionTable(reactionRateFlameArea, dictionary)
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:251
Omanip< int > setw(const int i)
Definition: IOmanip.H:199
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)
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
defineTypeNameAndDebug(combustionModel, 0)
tmp< DimensionedField< TypeR, GeoMesh > > New(const tmp< DimensionedField< TypeR, GeoMesh >> &tdf1, const word &name, const dimensionSet &dimensions)
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
static const char nl
Definition: Ostream.H:260
fileType type(const fileName &, const bool checkVariants=true, const bool followLink=true)
Return the file type: directory or file.
Definition: POSIX.C:488
runTime controlDict().lookup("adjustTimeStep") >> adjustTimeStep