1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
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.
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
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/>.
24 \*---------------------------------------------------------------------------*/
26 #include "pairGAMGAgglomeration.H"
27 #include "lduAddressing.H"
29 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
31 Foam::tmp<Foam::labelField> Foam::pairGAMGAgglomeration::agglomerate
34 const lduAddressing& fineMatrixAddressing,
35 const scalarField& faceWeights
38 const label nFineCells = fineMatrixAddressing.size();
40 const labelUList& upperAddr = fineMatrixAddressing.upperAddr();
41 const labelUList& lowerAddr = fineMatrixAddressing.lowerAddr();
43 // For each cell calculate faces
44 labelList cellFaces(upperAddr.size() + lowerAddr.size());
45 labelList cellFaceOffsets(nFineCells + 1);
49 labelList nNbrs(nFineCells, 0);
51 forAll(upperAddr, facei)
53 nNbrs[upperAddr[facei]]++;
56 forAll(lowerAddr, facei)
58 nNbrs[lowerAddr[facei]]++;
61 cellFaceOffsets[0] = 0;
64 cellFaceOffsets[celli+1] = cellFaceOffsets[celli] + nNbrs[celli];
67 // reset the whole list to use as counter
70 forAll(upperAddr, facei)
74 cellFaceOffsets[upperAddr[facei]] + nNbrs[upperAddr[facei]]
77 nNbrs[upperAddr[facei]]++;
80 forAll(lowerAddr, facei)
84 cellFaceOffsets[lowerAddr[facei]] + nNbrs[lowerAddr[facei]]
87 nNbrs[lowerAddr[facei]]++;
92 // go through the faces and create clusters
94 tmp<labelField> tcoarseCellMap(new labelField(nFineCells, -1));
95 labelField& coarseCellMap = tcoarseCellMap();
99 for (label celli=0; celli<nFineCells; celli++)
101 if (coarseCellMap[celli] < 0)
103 label matchFaceNo = -1;
104 scalar maxFaceWeight = -GREAT;
106 // check faces to find ungrouped neighbour with largest face weight
109 label faceOs=cellFaceOffsets[celli];
110 faceOs<cellFaceOffsets[celli+1];
114 label facei = cellFaces[faceOs];
116 // I don't know whether the current cell is owner or neighbour.
117 // Therefore I'll check both sides
120 coarseCellMap[upperAddr[facei]] < 0
121 && coarseCellMap[lowerAddr[facei]] < 0
122 && faceWeights[facei] > maxFaceWeight
125 // Match found. Pick up all the necessary data
127 maxFaceWeight = faceWeights[facei];
131 if (matchFaceNo >= 0)
134 coarseCellMap[upperAddr[matchFaceNo]] = nCoarseCells;
135 coarseCellMap[lowerAddr[matchFaceNo]] = nCoarseCells;
140 // No match. Find the best neighbouring cluster and
141 // put the cell there
142 label clusterMatchFaceNo = -1;
143 scalar clusterMaxFaceCoeff = -GREAT;
147 label faceOs=cellFaceOffsets[celli];
148 faceOs<cellFaceOffsets[celli+1];
152 label facei = cellFaces[faceOs];
154 if (faceWeights[facei] > clusterMaxFaceCoeff)
156 clusterMatchFaceNo = facei;
157 clusterMaxFaceCoeff = faceWeights[facei];
161 if (clusterMatchFaceNo >= 0)
163 // Add the cell to the best cluster
164 coarseCellMap[celli] = max
166 coarseCellMap[upperAddr[clusterMatchFaceNo]],
167 coarseCellMap[lowerAddr[clusterMatchFaceNo]]
175 // Check that all cells are part of clusters,
176 // if not create single-cell "clusters" for each
177 for (label celli=0; celli<nFineCells; celli++)
179 if (coarseCellMap[celli] < 0)
181 coarseCellMap[celli] = nCoarseCells;
186 // Reverese the map ordering to improve the next level of agglomeration
187 // (doesn't always help and is sometimes detrimental)
190 forAll(coarseCellMap, celli)
192 coarseCellMap[celli] = nCoarseCells - coarseCellMap[celli];
197 return tcoarseCellMap;
201 void Foam::pairGAMGAgglomeration::agglomerate
204 const scalarField& faceWeights
207 // Get the finest-level interfaces from the mesh
211 new lduInterfacePtrsList(mesh.interfaces())
214 // Start geometric agglomeration from the given faceWeights
215 scalarField* faceWeightsPtr = const_cast<scalarField*>(&faceWeights);
217 // Agglomerate until the required number of cells in the coarsest level
220 label nPairLevels = 0;
221 label nCreatedLevels = 0;
223 while (nCreatedLevels < maxLevels_ - 1)
225 label nCoarseCells = -1;
227 tmp<labelField> finalAgglomPtr = agglomerate
230 meshLevel(nCreatedLevels).lduAddr(),
234 if (continueAgglomerating(nCoarseCells))
236 nCells_[nCreatedLevels] = nCoarseCells;
237 restrictAddressing_.set(nCreatedLevels, finalAgglomPtr);
244 agglomerateLduAddressing(nCreatedLevels);
246 // Agglomerate the faceWeights field for the next level
248 scalarField* aggFaceWeightsPtr
252 meshLevels_[nCreatedLevels].upperAddr().size(),
266 delete faceWeightsPtr;
269 faceWeightsPtr = aggFaceWeightsPtr;
272 if (nPairLevels % mergeLevels_)
274 combineLevels(nCreatedLevels);
284 // Shrink the storage of the levels to those created
285 compactLevels(nCreatedLevels);
287 // Delete temporary geometry storage
290 delete faceWeightsPtr;
295 // ************************************************************************* //