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

GAMGSolverAgglomerateMatrix.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 "GAMGSolver.H"
00027 #include <OpenFOAM/GAMGInterfaceField.H>
00028 
00029 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
00030 
00031 void Foam::GAMGSolver::agglomerateMatrix(const label fineLevelIndex)
00032 {
00033     // Get fine matrix
00034     const lduMatrix& fineMatrix = matrixLevel(fineLevelIndex);
00035 
00036     // Set the coarse level matrix
00037     matrixLevels_.set
00038     (
00039         fineLevelIndex,
00040         new lduMatrix(agglomeration_.meshLevel(fineLevelIndex + 1))
00041     );
00042     lduMatrix& coarseMatrix = matrixLevels_[fineLevelIndex];
00043 
00044     // Get face restriction map for current level
00045     const labelList& faceRestrictAddr =
00046         agglomeration_.faceRestrictAddressing(fineLevelIndex);
00047 
00048     // Coarse matrix diagonal initialised by restricting the finer mesh diagonal
00049     scalarField& coarseDiag = coarseMatrix.diag();
00050     agglomeration_.restrictField(coarseDiag, fineMatrix.diag(), fineLevelIndex);
00051 
00052     // Get reference to fine-level interfaces
00053     const lduInterfaceFieldPtrsList& fineInterfaces =
00054         interfaceLevel(fineLevelIndex);
00055 
00056     // Get reference to fine-level boundary coefficients
00057     const FieldField<Field, scalar>& fineInterfaceBouCoeffs =
00058         interfaceBouCoeffsLevel(fineLevelIndex);
00059 
00060     // Get reference to fine-level internal coefficients
00061     const FieldField<Field, scalar>& fineInterfaceIntCoeffs =
00062         interfaceIntCoeffsLevel(fineLevelIndex);
00063 
00064 
00065     // Create coarse-level interfaces
00066     interfaceLevels_.set
00067     (
00068         fineLevelIndex,
00069         new lduInterfaceFieldPtrsList(fineInterfaces.size())
00070     );
00071 
00072     lduInterfaceFieldPtrsList& coarseInterfaces =
00073         interfaceLevels_[fineLevelIndex];
00074 
00075     // Set coarse-level boundary coefficients
00076     interfaceLevelsBouCoeffs_.set
00077     (
00078         fineLevelIndex,
00079         new FieldField<Field, scalar>(fineInterfaces.size())
00080     );
00081     FieldField<Field, scalar>& coarseInterfaceBouCoeffs =
00082         interfaceLevelsBouCoeffs_[fineLevelIndex];
00083 
00084     // Set coarse-level internal coefficients
00085     interfaceLevelsIntCoeffs_.set
00086     (
00087         fineLevelIndex,
00088         new FieldField<Field, scalar>(fineInterfaces.size())
00089     );
00090     FieldField<Field, scalar>& coarseInterfaceIntCoeffs =
00091         interfaceLevelsIntCoeffs_[fineLevelIndex];
00092 
00093     // Add the coarse level
00094     forAll (fineInterfaces, inti)
00095     {
00096         if (fineInterfaces.set(inti))
00097         {
00098             const GAMGInterface& coarseInterface = 
00099                 refCast<const GAMGInterface>
00100                 (
00101                     agglomeration_.interfaceLevel(fineLevelIndex + 1)[inti]
00102                 );
00103 
00104             coarseInterfaces.set
00105             (
00106                 inti,
00107                 GAMGInterfaceField::New
00108                 (
00109                     coarseInterface,
00110                     fineInterfaces[inti]
00111                 ).ptr()
00112             );
00113 
00114             coarseInterfaceBouCoeffs.set
00115             (
00116                 inti,
00117                 coarseInterface.agglomerateCoeffs(fineInterfaceBouCoeffs[inti])
00118             );
00119 
00120             coarseInterfaceIntCoeffs.set
00121             (
00122                 inti,
00123                 coarseInterface.agglomerateCoeffs(fineInterfaceIntCoeffs[inti])
00124             );
00125         }
00126     }
00127 
00128 
00129     // Check if matrix is assymetric and if so agglomerate both upper and lower
00130     // coefficients ...
00131     if (fineMatrix.hasLower())
00132     {
00133         // Get off-diagonal matrix coefficients
00134         const scalarField& fineUpper = fineMatrix.upper();
00135         const scalarField& fineLower = fineMatrix.lower();
00136 
00137         // Coarse matrix upper coefficients
00138         scalarField& coarseUpper = coarseMatrix.upper();
00139         scalarField& coarseLower = coarseMatrix.lower();
00140 
00141         const labelList& restrictAddr =
00142             agglomeration_.restrictAddressing(fineLevelIndex);
00143 
00144         const unallocLabelList& l = fineMatrix.lduAddr().lowerAddr();
00145         const unallocLabelList& cl = coarseMatrix.lduAddr().lowerAddr();
00146         const unallocLabelList& cu = coarseMatrix.lduAddr().upperAddr();
00147 
00148         forAll(faceRestrictAddr, fineFacei)
00149         {
00150             label cFace = faceRestrictAddr[fineFacei];
00151 
00152             if (cFace >= 0)
00153             {
00154                 // Check the orientation of the fine-face relative to the
00155                 // coarse face it is being agglomerated into
00156                 if (cl[cFace] == restrictAddr[l[fineFacei]])
00157                 {
00158                     coarseUpper[cFace] += fineUpper[fineFacei];
00159                     coarseLower[cFace] += fineLower[fineFacei];
00160                 }
00161                 else if (cu[cFace] == restrictAddr[l[fineFacei]])
00162                 {
00163                     coarseUpper[cFace] += fineLower[fineFacei];
00164                     coarseLower[cFace] += fineUpper[fineFacei];
00165                 }
00166                 else
00167                 {
00168                     FatalErrorIn
00169                     (
00170                         "GAMGSolver::agglomerateMatrix(const label)"
00171                     )   << "Inconsistent addressing between "
00172                            "fine and coarse grids"
00173                         << exit(FatalError);
00174                 }
00175             }
00176             else
00177             {
00178                 // Add the fine face coefficients into the diagonal.
00179                 coarseDiag[-1 - cFace] +=
00180                     fineUpper[fineFacei] + fineLower[fineFacei];
00181             }
00182         }
00183     }
00184     else // ... Otherwise it is symmetric so agglomerate just the upper 
00185     {
00186         // Get off-diagonal matrix coefficients
00187         const scalarField& fineUpper = fineMatrix.upper();
00188 
00189         // Coarse matrix upper coefficients
00190         scalarField& coarseUpper = coarseMatrix.upper();
00191 
00192         forAll(faceRestrictAddr, fineFacei)
00193         {
00194             label cFace = faceRestrictAddr[fineFacei];
00195 
00196             if (cFace >= 0)
00197             {
00198                 coarseUpper[cFace] += fineUpper[fineFacei];
00199             }
00200             else
00201             {
00202                 // Add the fine face coefficient into the diagonal.
00203                 coarseDiag[-1 - cFace] += 2*fineUpper[fineFacei];
00204             }
00205         }
00206     }
00207 }
00208 
00209 
00210 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines