1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2009 OpenCFD Ltd.
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 the
13 Free Software Foundation; either version 2 of the License, or (at your
14 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, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 \*---------------------------------------------------------------------------*/
27 #include "pairGAMGAgglomeration.H"
28 #include "lduAddressing.H"
30 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
32 Foam::tmp<Foam::labelField> Foam::pairGAMGAgglomeration::agglomerate
35 const lduAddressing& fineMatrixAddressing,
36 const scalarField& faceWeights
39 const label nFineCells = fineMatrixAddressing.size();
41 const unallocLabelList& upperAddr = fineMatrixAddressing.upperAddr();
42 const unallocLabelList& lowerAddr = fineMatrixAddressing.lowerAddr();
44 // For each cell calculate faces
45 labelList cellFaces(upperAddr.size() + lowerAddr.size());
46 labelList cellFaceOffsets(nFineCells + 1);
50 labelList nNbrs(nFineCells, 0);
52 forAll (upperAddr, facei)
54 nNbrs[upperAddr[facei]]++;
57 forAll (lowerAddr, facei)
59 nNbrs[lowerAddr[facei]]++;
62 cellFaceOffsets[0] = 0;
65 cellFaceOffsets[celli+1] = cellFaceOffsets[celli] + nNbrs[celli];
68 // reset the whole list to use as counter
71 forAll (upperAddr, facei)
75 cellFaceOffsets[upperAddr[facei]] + nNbrs[upperAddr[facei]]
78 nNbrs[upperAddr[facei]]++;
81 forAll (lowerAddr, facei)
85 cellFaceOffsets[lowerAddr[facei]] + nNbrs[lowerAddr[facei]]
88 nNbrs[lowerAddr[facei]]++;
93 // go through the faces and create clusters
95 tmp<labelField> tcoarseCellMap(new labelField(nFineCells, -1));
96 labelField& coarseCellMap = tcoarseCellMap();
100 for (label celli=0; celli<nFineCells; celli++)
102 if (coarseCellMap[celli] < 0)
104 label matchFaceNo = -1;
105 scalar maxFaceWeight = -GREAT;
107 // check faces to find ungrouped neighbour with largest face weight
110 label faceOs=cellFaceOffsets[celli];
111 faceOs<cellFaceOffsets[celli+1];
115 label facei = cellFaces[faceOs];
117 // I don't know whether the current cell is owner or neighbour.
118 // Therefore I'll check both sides
121 coarseCellMap[upperAddr[facei]] < 0
122 && coarseCellMap[lowerAddr[facei]] < 0
123 && faceWeights[facei] > maxFaceWeight
126 // Match found. Pick up all the necessary data
128 maxFaceWeight = faceWeights[facei];
132 if (matchFaceNo >= 0)
135 coarseCellMap[upperAddr[matchFaceNo]] = nCoarseCells;
136 coarseCellMap[lowerAddr[matchFaceNo]] = nCoarseCells;
141 // No match. Find the best neighbouring cluster and
142 // put the cell there
143 label clusterMatchFaceNo = -1;
144 scalar clusterMaxFaceCoeff = -GREAT;
148 label faceOs=cellFaceOffsets[celli];
149 faceOs<cellFaceOffsets[celli+1];
153 label facei = cellFaces[faceOs];
155 if (faceWeights[facei] > clusterMaxFaceCoeff)
157 clusterMatchFaceNo = facei;
158 clusterMaxFaceCoeff = faceWeights[facei];
162 if (clusterMatchFaceNo >= 0)
164 // Add the cell to the best cluster
165 coarseCellMap[celli] = max
167 coarseCellMap[upperAddr[clusterMatchFaceNo]],
168 coarseCellMap[lowerAddr[clusterMatchFaceNo]]
176 // Check that all cells are part of clusters,
177 // if not create single-cell "clusters" for each
178 for (label celli=0; celli<nFineCells; celli++)
180 if (coarseCellMap[celli] < 0)
182 coarseCellMap[celli] = nCoarseCells;
187 // Reverese the map ordering to improve the next level of agglomeration
188 // (doesn't always help and is sometimes detrimental)
191 forAll (coarseCellMap, celli)
193 coarseCellMap[celli] = nCoarseCells - coarseCellMap[celli];
198 return tcoarseCellMap;
202 void Foam::pairGAMGAgglomeration::agglomerate
205 const scalarField& faceWeights
208 // Get the finest-level interfaces from the mesh
212 new lduInterfacePtrsList(mesh.interfaces())
215 // Start geometric agglomeration from the given faceWeights
216 scalarField* faceWeightsPtr = const_cast<scalarField*>(&faceWeights);
218 // Agglomerate until the required number of cells in the coarsest level
221 label nPairLevels = 0;
222 label nCreatedLevels = 0;
224 while (nCreatedLevels < maxLevels_ - 1)
226 label nCoarseCells = -1;
228 tmp<labelField> finalAgglomPtr = agglomerate
231 meshLevel(nCreatedLevels).lduAddr(),
235 if (continueAgglomerating(nCoarseCells))
237 nCells_[nCreatedLevels] = nCoarseCells;
238 restrictAddressing_.set(nCreatedLevels, finalAgglomPtr);
245 agglomerateLduAddressing(nCreatedLevels);
247 // Agglomerate the faceWeights field for the next level
249 scalarField* aggFaceWeightsPtr
253 meshLevels_[nCreatedLevels].upperAddr().size(),
267 delete faceWeightsPtr;
270 faceWeightsPtr = aggFaceWeightsPtr;
273 if (nPairLevels % mergeLevels_)
275 combineLevels(nCreatedLevels);
285 // Shrink the storage of the levels to those created
286 compactLevels(nCreatedLevels);
288 // Delete temporary geometry storage
291 delete faceWeightsPtr;
296 // ************************************************************************* //