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 | Copyright (C) 2011-2015 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 {
39  defineTypeNameAndDebug(GAMGAgglomeration, 0);
40  defineRunTimeSelectionTable(GAMGAgglomeration, lduMesh);
41  defineRunTimeSelectionTable(GAMGAgglomeration, lduMatrix);
42  defineRunTimeSelectionTable(GAMGAgglomeration, geometry);
43 }
44 
45 
46 // * * * * * * * * * * * * * Private 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);
61  if (processorAgglomerate())
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;
80  if (processorAgglomerate())
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 nCoarseCells
210 ) const
211 {
212  // Check the need for further agglomeration on all processors
213  bool contAgg = nCoarseCells >= nCellsInCoarsestLevel_;
214  mesh().reduce(contAgg, andOp<bool>());
215  return contAgg;
216 }
217 
218 
219 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
220 
221 Foam::GAMGAgglomeration::GAMGAgglomeration
222 (
223  const lduMesh& mesh,
224  const dictionary& controlDict
225 )
226 :
228 
229  maxLevels_(50),
230 
231  nCellsInCoarsestLevel_
232  (
233  controlDict.lookupOrDefault<label>("nCellsInCoarsestLevel", 10)
234  ),
235  meshInterfaces_(mesh.interfaces()),
236  procAgglomeratorPtr_
237  (
238  (
239  (UPstream::nProcs(mesh.comm()) > 1)
240  && controlDict.found("processorAgglomerator")
241  )
243  (
244  controlDict.lookup("processorAgglomerator"),
245  *this,
247  )
249  ),
250 
251  nCells_(maxLevels_),
252  restrictAddressing_(maxLevels_),
253  nFaces_(maxLevels_),
254  faceRestrictAddressing_(maxLevels_),
255  faceFlipMap_(maxLevels_),
256  nPatchFaces_(maxLevels_),
257  patchFaceRestrictAddressing_(maxLevels_),
258 
259  meshLevels_(maxLevels_)
260 {
261  procCommunicator_.setSize(maxLevels_ + 1, -1);
262  if (processorAgglomerate())
263  {
264  procAgglomMap_.setSize(maxLevels_);
265  agglomProcIDs_.setSize(maxLevels_);
266  procCellOffsets_.setSize(maxLevels_);
267  procFaceMap_.setSize(maxLevels_);
268  procBoundaryMap_.setSize(maxLevels_);
269  procBoundaryFaceMap_.setSize(maxLevels_);
270  }
271 }
272 
273 
275 (
276  const lduMesh& mesh,
277  const dictionary& controlDict
278 )
279 {
280  if
281  (
283  (
284  GAMGAgglomeration::typeName
285  )
286  )
287  {
288  const word agglomeratorType
289  (
290  controlDict.lookupOrDefault<word>("agglomerator", "faceAreaPair")
291  );
292 
293  const_cast<Time&>(mesh.thisDb().time()).libs().open
294  (
295  controlDict,
296  "geometricGAMGAgglomerationLibs",
297  lduMeshConstructorTablePtr_
298  );
299 
300  lduMeshConstructorTable::iterator cstrIter =
301  lduMeshConstructorTablePtr_->find(agglomeratorType);
302 
303  if (cstrIter == lduMeshConstructorTablePtr_->end())
304  {
306  (
307  "GAMGAgglomeration::New"
308  "(const lduMesh& mesh, const dictionary& controlDict)"
309  ) << "Unknown GAMGAgglomeration type "
310  << agglomeratorType << ".\n"
311  << "Valid matrix GAMGAgglomeration types are :"
312  << lduMatrixConstructorTablePtr_->sortedToc() << endl
313  << "Valid geometric GAMGAgglomeration types are :"
314  << lduMeshConstructorTablePtr_->sortedToc()
315  << exit(FatalError);
316  }
317 
318  return store(cstrIter()(mesh, controlDict).ptr());
319  }
320  else
321  {
322  return mesh.thisDb().lookupObject<GAMGAgglomeration>
323  (
324  GAMGAgglomeration::typeName
325  );
326  }
327 }
328 
329 
331 (
332  const lduMatrix& matrix,
333  const dictionary& controlDict
334 )
335 {
336  const lduMesh& mesh = matrix.mesh();
337 
338  if
339  (
341  (
342  GAMGAgglomeration::typeName
343  )
344  )
345  {
346  const word agglomeratorType
347  (
348  controlDict.lookupOrDefault<word>("agglomerator", "faceAreaPair")
349  );
350 
351  const_cast<Time&>(mesh.thisDb().time()).libs().open
352  (
353  controlDict,
354  "algebraicGAMGAgglomerationLibs",
355  lduMatrixConstructorTablePtr_
356  );
357 
358  if
359  (
360  !lduMatrixConstructorTablePtr_
361  || !lduMatrixConstructorTablePtr_->found(agglomeratorType)
362  )
363  {
364  return New(mesh, controlDict);
365  }
366  else
367  {
368  lduMatrixConstructorTable::iterator cstrIter =
369  lduMatrixConstructorTablePtr_->find(agglomeratorType);
370 
371  return store(cstrIter()(matrix, controlDict).ptr());
372  }
373  }
374  else
375  {
376  return mesh.thisDb().lookupObject<GAMGAgglomeration>
377  (
378  GAMGAgglomeration::typeName
379  );
380  }
381 }
382 
383 
385 (
386  const lduMesh& mesh,
387  const scalarField& cellVolumes,
388  const vectorField& faceAreas,
389  const dictionary& controlDict
390 )
391 {
392  const word agglomeratorType
393  (
394  controlDict.lookupOrDefault<word>("agglomerator", "faceAreaPair")
395  );
396 
397  const_cast<Time&>(mesh.thisDb().time()).libs().open
398  (
399  controlDict,
400  "geometricGAMGAgglomerationLibs",
401  geometryConstructorTablePtr_
402  );
403 
404  geometryConstructorTable::iterator cstrIter =
405  geometryConstructorTablePtr_->find(agglomeratorType);
406 
407  if (cstrIter == geometryConstructorTablePtr_->end())
408  {
410  (
411  "GAMGAgglomeration::New"
412  "(const lduMesh& mesh, const scalarField&"
413  ", const vectorField&, const dictionary& controlDict)"
414  ) << "Unknown GAMGAgglomeration type "
415  << agglomeratorType << ".\n"
416  << "Valid geometric GAMGAgglomeration types are :"
417  << geometryConstructorTablePtr_->sortedToc()
418  << exit(FatalError);
419  }
420 
422  (
423  cstrIter()
424  (
425  mesh,
426  cellVolumes,
427  faceAreas,
429  )
430  );
431 }
432 
433 
434 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
435 
437 {}
438 
439 
440 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
441 
443 (
444  const label i
445 ) const
446 {
447  if (i == 0)
448  {
449  return mesh_;
450  }
451  else
452  {
453  return meshLevels_[i - 1];
454  }
455 }
456 
457 
459 {
460  if (i == 0)
461  {
462  return true;
463  }
464  else
465  {
466  return meshLevels_.set(i - 1);
467  }
468 }
469 
470 
472 (
473  const label i
474 ) const
475 {
476  if (i == 0)
477  {
478  return meshInterfaces_;
479  }
480  else
481  {
482  return meshLevels_[i - 1].rawInterfaces();
483  }
484 }
485 
486 
488 {
489  if (hasMeshLevel(i))
490  {
491  meshLevels_.set(i - 1, NULL);
492 
493  if (i < nCells_.size())
494  {
495  nCells_[i] = -555;
496  restrictAddressing_.set(i, NULL);
497  nFaces_[i] = -666;
498  faceRestrictAddressing_.set(i, NULL);
499  faceFlipMap_.set(i, NULL);
500  nPatchFaces_.set(i, NULL);
501  patchFaceRestrictAddressing_.set(i, NULL);
502  }
503  }
504 }
505 
506 
508 (
509  const label leveli
510 ) const
511 {
512  return procAgglomMap_[leveli];
513 }
514 
515 
517 (
518  const label leveli
519 ) const
520 {
521  return agglomProcIDs_[leveli];
522 }
523 
524 
526 {
527  return procCommunicator_[leveli] != -1;
528 }
529 
530 
532 {
533  return procCommunicator_[leveli];
534 }
535 
536 
538 (
539  const label leveli
540 ) const
541 {
542  return procCellOffsets_[leveli];
543 }
544 
545 
547 (
548  const label leveli
549 ) const
550 {
551  return procFaceMap_[leveli];
552 }
553 
554 
556 (
557  const label leveli
558 ) const
559 {
560  return procBoundaryMap_[leveli];
561 }
562 
563 
565 (
566  const label leveli
567 ) const
568 {
569  return procBoundaryFaceMap_[leveli];
570 }
571 
572 
574 (
575  labelList& newRestrict,
576  label& nNewCoarse,
577  const lduAddressing& fineAddressing,
578  const labelUList& restrict,
579  const label nCoarse
580 )
581 {
582  if (fineAddressing.size() != restrict.size())
583  {
585  (
586  "checkRestriction(..)"
587  ) << "nCells:" << fineAddressing.size()
588  << " agglom:" << restrict.size()
589  << abort(FatalError);
590  }
591 
592  // Seed (master) for every region
593  labelList master(identity(fineAddressing.size()));
594 
595  // Now loop and transport master through region
596  const labelUList& lower = fineAddressing.lowerAddr();
597  const labelUList& upper = fineAddressing.upperAddr();
598 
599  while (true)
600  {
601  label nChanged = 0;
602 
603  forAll(lower, faceI)
604  {
605  label own = lower[faceI];
606  label nei = upper[faceI];
607 
608  if (restrict[own] == restrict[nei])
609  {
610  // coarse-mesh-internal face
611 
612  if (master[own] < master[nei])
613  {
614  master[nei] = master[own];
615  nChanged++;
616  }
617  else if (master[own] > master[nei])
618  {
619  master[own] = master[nei];
620  nChanged++;
621  }
622  }
623  }
624 
625  reduce(nChanged, sumOp<label>());
626 
627  if (nChanged == 0)
628  {
629  break;
630  }
631  }
632 
633 
634  // Count number of regions/masters per coarse cell
635  labelListList coarseToMasters(nCoarse);
636  nNewCoarse = 0;
637  forAll(restrict, cellI)
638  {
639  labelList& masters = coarseToMasters[restrict[cellI]];
640 
641  if (findIndex(masters, master[cellI]) == -1)
642  {
643  masters.append(master[cellI]);
644  nNewCoarse++;
645  }
646  }
647 
648  if (nNewCoarse > nCoarse)
649  {
650  //WarningIn("GAMGAgglomeration::checkRestriction(..)")
651  // << "Have " << nCoarse
652  // << " agglomerated cells but " << nNewCoarse
653  // << " disconnected regions" << endl;
654 
655  // Keep coarseToMasters[0] the original coarse, allocate new ones
656  // for the others
657  labelListList coarseToNewCoarse(coarseToMasters.size());
658 
659  nNewCoarse = nCoarse;
660 
661  forAll(coarseToMasters, coarseI)
662  {
663  const labelList& masters = coarseToMasters[coarseI];
664 
665  labelList& newCoarse = coarseToNewCoarse[coarseI];
666  newCoarse.setSize(masters.size());
667  newCoarse[0] = coarseI;
668  for (label i = 1; i < newCoarse.size(); i++)
669  {
670  newCoarse[i] = nNewCoarse++;
671  }
672  }
673 
674  newRestrict.setSize(fineAddressing.size());
675  forAll(restrict, cellI)
676  {
677  label coarseI = restrict[cellI];
678 
679  label index = findIndex(coarseToMasters[coarseI], master[cellI]);
680  newRestrict[cellI] = coarseToNewCoarse[coarseI][index];
681  }
682 
683  return false;
684  }
685  else
686  {
687  return true;
688  }
689 }
690 
691 
692 // ************************************************************************* //
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
bool continueAgglomerating(const label nCoarseCells) const
Check the need for further agglomeration.
bool found(const word &, bool recursive=false, bool patternMatch=true) const
Search dictionary for given keyword.
Definition: dictionary.C:306
label size() const
Return number of equations.
virtual const labelUList & upperAddr() const =0
Return upper addressing.
const labelListList & boundaryMap(const label fineLeveli) const
Mapping from processor to procMesh boundary.
void reduce(T &Value, const BinaryOp &bop) const
Helper: reduce with current communicator.
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 occurence of given element and return index,.
virtual label comm() const =0
Return communicator used for parallel communication.
const labelList & cellOffsets(const label fineLeveli) const
Mapping from processor to procMesh cells.
Geometric agglomerated algebraic multigrid agglomeration class.
bool foundObject(const word &name) const
Is the named Type found?
static autoPtr< GAMGProcAgglomeration > New(const word &type, GAMGAgglomeration &agglom, const dictionary &controlDict)
Return the selected agglomerator.
virtual lduInterfacePtrsList interfaces() const =0
Return a list of pointers for each patch.
static const GAMGAgglomeration & New(const lduMesh &mesh, const dictionary &controlDict)
Return the selected geometric agglomerator.
A class for handling words, derived from string.
Definition: word.H:59
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
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:76
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
messageStream Info
Abstract base class for meshes which provide LDU addressing for the construction of lduMatrix and LDU...
Definition: lduMesh.H:51
static bool checkRestriction(labelList &newRestrict, label &nNewCoarse, const lduAddressing &fineAddressing, const labelUList &restrict, const label nCoarse)
Given restriction determines if coarse cells are connected.
dynamicFvMesh & mesh
A list of keyword definitions, which are a keyword followed by any number of values (e...
Definition: dictionary.H:137
virtual const objectRegistry & thisDb() const
Return the object registry.
Definition: lduMesh.C:40
Namespace for OpenFOAM.
autoPtr< BasicCompressibleTurbulenceModel > New(const volScalarField &rho, const volVectorField &U, const surfaceScalarField &phi, const typename BasicCompressibleTurbulenceModel::transportModel &transport, const word &propertiesName)
const labelList & procAgglomMap(const label fineLeveli) const
Mapping from processor to agglomerated processor (global, all.
virtual const lduAddressing & lduAddr() const =0
Return ldu addressing.
const lduMesh & meshLevel(const label leveli) const
Return LDU mesh of given level.
Tuple2< label, scalar > band() const
Calculate bandwidth and profile of addressing.
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:68
const labelListList & faceMap(const label fineLeveli) const
Mapping from processor to procMesh face.
static label nProcs(const label communicator=0)
Number of processes in parallel run.
Definition: UPstream.H:386
static const char nl
Definition: Ostream.H:260
void setSize(const label)
Reset size of List.
Definition: List.C:318
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
const labelListListList & boundaryFaceMap(const label fineLeveli) const
Mapping from processor to procMesh boundary face.
bool hasMeshLevel(const label leveli) const
Do we have mesh for given level?
lduMatrix is a general matrix class in which the coefficients are stored as three arrays...
Definition: lduMatrix.H:77
#define forAll(list, i)
Definition: UList.H:421
const Type & lookupObject(const word &name) const
Lookup and return the object of the given Type.
label size() const
Return the number of elements in the UList.
Definition: UListI.H:299
virtual const labelUList & lowerAddr() const =0
Return lower addressing.
Omanip< int > setw(const int i)
Definition: IOmanip.H:199
labelList identity(const label len)
Create identity map (map[i] == i) of given length.
Definition: ListOps.C:104
errorManip< error > abort(error &err)
Definition: errorManip.H:131
Templated abstract base-class for optional mesh objects used to automate their allocation to the mesh...
Definition: MeshObject.H:81
fileName::Type type(const fileName &)
Return the file type: DIRECTORY or FILE.
Definition: POSIX.C:589
Istream and Ostream manipulators taking arguments.
void compactLevels(const label nCreatedLevels)
Shrink the number of levels to that specified.
#define FatalErrorIn(functionName)
Report an error message using Foam::FatalError.
Definition: error.H:314
const labelList & agglomProcIDs(const label fineLeveli) const
Set of processors to agglomerate. Element 0 is the.
ITstream & lookup(const word &, bool recursive=false, bool patternMatch=true) const
Find and return an entry data stream.
Definition: dictionary.C:452
error FatalError
T lookupOrDefault(const word &, const T &, bool recursive=false, bool patternMatch=true) const
Find and return a T,.
void clearLevel(const label leveli)
runTime controlDict().lookup("adjustTimeStep") >> adjustTimeStep
bool hasProcMesh(const label fineLeveli) const
Check that level has combined mesh.
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition: HashTable.H:60
const lduInterfacePtrsList & interfaceLevel(const label leveli) const
Return LDU interface addressing of given level.
defineRunTimeSelectionTable(reactionRateFlameArea, dictionary)
const lduMesh & mesh() const
Return the LDU mesh from which the addressing is obtained.
Definition: lduMatrix.H:544
void append(const T &)
Append an element at the end of the list.
Definition: ListI.H:97
const Time & time() const
Return time.
The class contains the addressing required by the lduMatrix: upper, lower and losort.
iterator find(const Key &)
Find and return an iterator set at the hashedEntry.
Definition: HashTable.C:139
~GAMGAgglomeration()
Destructor.
An auto-pointer similar to the STL auto_ptr but with automatic casting to a reference to the type and...
Definition: PtrList.H:117
label procCommunicator(const label fineLeveli) const
Communicator for current level or -1.
defineTypeNameAndDebug(combustionModel, 0)