FreeFOAM The Cross-Platform CFD Toolkit
Hosted by SourceForge:
Get FreeFOAM at SourceForge.net.
            Fast, secure and Free Open Source software downloads

pairGAMGAgglomerate.C

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002   =========                 |
00003   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
00004    \\    /   O peration     |
00005     \\  /    A nd           | Copyright (C) 1991-2010 OpenCFD Ltd.
00006      \\/     M anipulation  |
00007 -------------------------------------------------------------------------------
00008 License
00009     This file is part of OpenFOAM.
00010 
00011     OpenFOAM is free software: you can redistribute it and/or modify it
00012     under the terms of the GNU General Public License as published by
00013     the Free Software Foundation, either version 3 of the License, or
00014     (at your option) any later version.
00015 
00016     OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
00017     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00019     for more details.
00020 
00021     You should have received a copy of the GNU General Public License
00022     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
00023 
00024 \*---------------------------------------------------------------------------*/
00025 
00026 #include "pairGAMGAgglomeration.H"
00027 #include <OpenFOAM/lduAddressing.H>
00028 
00029 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
00030 
00031 Foam::tmp<Foam::labelField> Foam::pairGAMGAgglomeration::agglomerate
00032 (
00033     label& nCoarseCells,
00034     const lduAddressing& fineMatrixAddressing,
00035     const scalarField& faceWeights
00036 )
00037 {
00038     const label nFineCells = fineMatrixAddressing.size();
00039 
00040     const unallocLabelList& upperAddr = fineMatrixAddressing.upperAddr();
00041     const unallocLabelList& lowerAddr = fineMatrixAddressing.lowerAddr();
00042 
00043     // For each cell calculate faces
00044     labelList cellFaces(upperAddr.size() + lowerAddr.size());
00045     labelList cellFaceOffsets(nFineCells + 1);
00046 
00047     // memory management
00048     {
00049         labelList nNbrs(nFineCells, 0);
00050 
00051         forAll (upperAddr, facei)
00052         {
00053             nNbrs[upperAddr[facei]]++;
00054         }
00055 
00056         forAll (lowerAddr, facei)
00057         {
00058             nNbrs[lowerAddr[facei]]++;
00059         }
00060 
00061         cellFaceOffsets[0] = 0;
00062         forAll (nNbrs, celli)
00063         {
00064             cellFaceOffsets[celli+1] = cellFaceOffsets[celli] + nNbrs[celli];
00065         }
00066 
00067         // reset the whole list to use as counter
00068         nNbrs = 0;
00069 
00070         forAll (upperAddr, facei)
00071         {
00072             cellFaces
00073             [
00074                 cellFaceOffsets[upperAddr[facei]] + nNbrs[upperAddr[facei]]
00075             ] = facei;
00076 
00077             nNbrs[upperAddr[facei]]++;
00078         }
00079 
00080         forAll (lowerAddr, facei)
00081         {
00082             cellFaces
00083             [
00084                 cellFaceOffsets[lowerAddr[facei]] + nNbrs[lowerAddr[facei]]
00085             ] = facei;
00086 
00087             nNbrs[lowerAddr[facei]]++;
00088         }
00089     }
00090 
00091 
00092     // go through the faces and create clusters
00093 
00094     tmp<labelField> tcoarseCellMap(new labelField(nFineCells, -1));
00095     labelField& coarseCellMap = tcoarseCellMap();
00096 
00097     nCoarseCells = 0;
00098 
00099     for (label celli=0; celli<nFineCells; celli++)
00100     {
00101         if (coarseCellMap[celli] < 0)
00102         {
00103             label matchFaceNo = -1;
00104             scalar maxFaceWeight = -GREAT;
00105 
00106             // check faces to find ungrouped neighbour with largest face weight
00107             for
00108             (
00109                 label faceOs=cellFaceOffsets[celli];
00110                 faceOs<cellFaceOffsets[celli+1];
00111                 faceOs++
00112             )
00113             {
00114                 label facei = cellFaces[faceOs];
00115 
00116                 // I don't know whether the current cell is owner or neighbour.
00117                 // Therefore I'll check both sides
00118                 if
00119                 (
00120                     coarseCellMap[upperAddr[facei]] < 0
00121                  && coarseCellMap[lowerAddr[facei]] < 0
00122                  && faceWeights[facei] > maxFaceWeight
00123                 )
00124                 {
00125                     // Match found. Pick up all the necessary data
00126                     matchFaceNo = facei;
00127                     maxFaceWeight = faceWeights[facei];
00128                 }
00129             }
00130 
00131             if (matchFaceNo >= 0)
00132             {
00133                 // Make a new group
00134                 coarseCellMap[upperAddr[matchFaceNo]] = nCoarseCells;
00135                 coarseCellMap[lowerAddr[matchFaceNo]] = nCoarseCells;
00136                 nCoarseCells++;
00137             }
00138             else
00139             {
00140                 // No match. Find the best neighbouring cluster and
00141                 // put the cell there
00142                 label clusterMatchFaceNo = -1;
00143                 scalar clusterMaxFaceCoeff = -GREAT;
00144 
00145                 for
00146                 (
00147                     label faceOs=cellFaceOffsets[celli];
00148                     faceOs<cellFaceOffsets[celli+1];
00149                     faceOs++
00150                 )
00151                 {
00152                     label facei = cellFaces[faceOs];
00153 
00154                     if (faceWeights[facei] > clusterMaxFaceCoeff)
00155                     {
00156                         clusterMatchFaceNo = facei;
00157                         clusterMaxFaceCoeff = faceWeights[facei];
00158                     }
00159                 }
00160 
00161                 if (clusterMatchFaceNo >= 0)
00162                 {
00163                     // Add the cell to the best cluster
00164                     coarseCellMap[celli] = max
00165                     (
00166                         coarseCellMap[upperAddr[clusterMatchFaceNo]],
00167                         coarseCellMap[lowerAddr[clusterMatchFaceNo]]
00168                     );
00169                 }
00170             }
00171         }
00172     }
00173 
00174 
00175     // Check that all cells are part of clusters,
00176     // if not create single-cell "clusters" for each
00177     for (label celli=0; celli<nFineCells; celli++)
00178     {
00179         if (coarseCellMap[celli] < 0)
00180         {
00181             coarseCellMap[celli] = nCoarseCells;
00182             nCoarseCells++;
00183         }
00184     }
00185 
00186     // Reverese the map ordering to improve the next level of agglomeration
00187     // (doesn't always help and is sometimes detrimental)
00188     nCoarseCells--;
00189 
00190     forAll (coarseCellMap, celli)
00191     {
00192         coarseCellMap[celli] = nCoarseCells - coarseCellMap[celli];
00193     }
00194 
00195     nCoarseCells++;
00196 
00197     return tcoarseCellMap;
00198 }
00199 
00200 
00201 void Foam::pairGAMGAgglomeration::agglomerate
00202 (
00203     const lduMesh& mesh,
00204     const scalarField& faceWeights
00205 )
00206 {
00207     // Get the finest-level interfaces from the mesh
00208     interfaceLevels_.set
00209     (
00210         0,
00211         new lduInterfacePtrsList(mesh.interfaces())
00212     );
00213 
00214     // Start geometric agglomeration from the given faceWeights
00215     scalarField* faceWeightsPtr = const_cast<scalarField*>(&faceWeights);
00216 
00217     // Agglomerate until the required number of cells in the coarsest level
00218     // is reached
00219 
00220     label nPairLevels = 0;
00221     label nCreatedLevels = 0;
00222 
00223     while (nCreatedLevels < maxLevels_ - 1)
00224     {
00225         label nCoarseCells = -1;
00226 
00227         tmp<labelField> finalAgglomPtr = agglomerate
00228         (
00229             nCoarseCells,
00230             meshLevel(nCreatedLevels).lduAddr(),
00231             *faceWeightsPtr
00232         );
00233 
00234         if (continueAgglomerating(nCoarseCells))
00235         {
00236             nCells_[nCreatedLevels] = nCoarseCells;
00237             restrictAddressing_.set(nCreatedLevels, finalAgglomPtr);
00238         }
00239         else
00240         {
00241             break;
00242         }
00243 
00244         agglomerateLduAddressing(nCreatedLevels);
00245 
00246         // Agglomerate the faceWeights field for the next level
00247         {
00248             scalarField* aggFaceWeightsPtr
00249             (
00250                 new scalarField
00251                 (
00252                     meshLevels_[nCreatedLevels].upperAddr().size(),
00253                     0.0
00254                 )
00255             );
00256 
00257             restrictFaceField
00258             (
00259                 *aggFaceWeightsPtr,
00260                 *faceWeightsPtr,
00261                 nCreatedLevels
00262             );
00263 
00264             if (nCreatedLevels)
00265             {
00266                 delete faceWeightsPtr;
00267             }
00268 
00269             faceWeightsPtr = aggFaceWeightsPtr;
00270         }
00271 
00272         if (nPairLevels % mergeLevels_)
00273         {
00274             combineLevels(nCreatedLevels);
00275         }
00276         else
00277         {
00278             nCreatedLevels++;
00279         }
00280 
00281         nPairLevels++;
00282     }
00283 
00284     // Shrink the storage of the levels to those created
00285     compactLevels(nCreatedLevels);
00286 
00287     // Delete temporary geometry storage
00288     if (nCreatedLevels)
00289     {
00290         delete faceWeightsPtr;
00291     }
00292 }
00293 
00294 
00295 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines