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

GaussSeidelSmoother.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 <OpenFOAM/GaussSeidelSmoother.H>
00027 
00028 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
00029 
00030 namespace Foam
00031 {
00032     defineTypeNameAndDebug(GaussSeidelSmoother, 0);
00033 
00034     lduMatrix::smoother::addsymMatrixConstructorToTable<GaussSeidelSmoother>
00035         addGaussSeidelSmootherSymMatrixConstructorToTable_;
00036 
00037     lduMatrix::smoother::addasymMatrixConstructorToTable<GaussSeidelSmoother>
00038         addGaussSeidelSmootherAsymMatrixConstructorToTable_;
00039 }
00040 
00041 
00042 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
00043 
00044 Foam::GaussSeidelSmoother::GaussSeidelSmoother
00045 (
00046     const word& fieldName,
00047     const lduMatrix& matrix,
00048     const FieldField<Field, scalar>& interfaceBouCoeffs,
00049     const FieldField<Field, scalar>& interfaceIntCoeffs,
00050     const lduInterfaceFieldPtrsList& interfaces
00051 )
00052 :
00053     lduMatrix::smoother
00054     (
00055         fieldName,
00056         matrix,
00057         interfaceBouCoeffs,
00058         interfaceIntCoeffs,
00059         interfaces
00060     )
00061 {}
00062 
00063 
00064 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
00065 
00066 void Foam::GaussSeidelSmoother::smooth
00067 (
00068     const word& fieldName_,
00069     scalarField& psi,
00070     const lduMatrix& matrix_,
00071     const scalarField& source,
00072     const FieldField<Field, scalar>& interfaceBouCoeffs_,
00073     const lduInterfaceFieldPtrsList& interfaces_,
00074     const direction cmpt,
00075     const label nSweeps
00076 )
00077 {
00078     register scalar* __restrict__ psiPtr = psi.begin();
00079 
00080     register const label nCells = psi.size();
00081 
00082     scalarField bPrime(nCells);
00083     register scalar* __restrict__ bPrimePtr = bPrime.begin();
00084 
00085     register const scalar* const __restrict__ diagPtr = matrix_.diag().begin();
00086     register const scalar* const __restrict__ upperPtr =
00087         matrix_.upper().begin();
00088     register const scalar* const __restrict__ lowerPtr =
00089         matrix_.lower().begin();
00090 
00091     register const label* const __restrict__ uPtr =
00092         matrix_.lduAddr().upperAddr().begin();
00093 
00094     register const label* const __restrict__ ownStartPtr =
00095         matrix_.lduAddr().ownerStartAddr().begin();
00096 
00097 
00098     // Parallel boundary initialisation.  The parallel boundary is treated
00099     // as an effective jacobi interface in the boundary.
00100     // Note: there is a change of sign in the coupled
00101     // interface update.  The reason for this is that the
00102     // internal coefficients are all located at the l.h.s. of
00103     // the matrix whereas the "implicit" coefficients on the
00104     // coupled boundaries are all created as if the
00105     // coefficient contribution is of a source-kind (i.e. they
00106     // have a sign as if they are on the r.h.s. of the matrix.
00107     // To compensate for this, it is necessary to turn the
00108     // sign of the contribution.
00109 
00110     FieldField<Field, scalar> mBouCoeffs(interfaceBouCoeffs_.size());
00111 
00112     forAll(mBouCoeffs, patchi)
00113     {
00114         if (interfaces_.set(patchi))
00115         {
00116             mBouCoeffs.set(patchi, -interfaceBouCoeffs_[patchi]);
00117         }
00118     }
00119 
00120     for (label sweep=0; sweep<nSweeps; sweep++)
00121     {
00122         bPrime = source;
00123 
00124         matrix_.initMatrixInterfaces
00125         (
00126             mBouCoeffs,
00127             interfaces_,
00128             psi,
00129             bPrime,
00130             cmpt
00131         );
00132 
00133         matrix_.updateMatrixInterfaces
00134         (
00135             mBouCoeffs,
00136             interfaces_,
00137             psi,
00138             bPrime,
00139             cmpt
00140         );
00141 
00142         register scalar curPsi;
00143         register label fStart;
00144         register label fEnd = ownStartPtr[0];
00145 
00146         for (register label cellI=0; cellI<nCells; cellI++)
00147         {
00148             // Start and end of this row
00149             fStart = fEnd;
00150             fEnd = ownStartPtr[cellI + 1];
00151 
00152             // Get the accumulated neighbour side
00153             curPsi = bPrimePtr[cellI];
00154 
00155             // Accumulate the owner product side
00156             for (register label curFace=fStart; curFace<fEnd; curFace++)
00157             {
00158                 curPsi -= upperPtr[curFace]*psiPtr[uPtr[curFace]];
00159             }
00160 
00161             // Finish current psi
00162             curPsi /= diagPtr[cellI];
00163 
00164             // Distribute the neighbour side using current psi
00165             for (register label curFace=fStart; curFace<fEnd; curFace++)
00166             {
00167                 bPrimePtr[uPtr[curFace]] -= lowerPtr[curFace]*curPsi;
00168             }
00169 
00170             psiPtr[cellI] = curPsi;
00171         }
00172     }
00173 }
00174 
00175 
00176 void Foam::GaussSeidelSmoother::smooth
00177 (
00178     scalarField& psi,
00179     const scalarField& source,
00180     const direction cmpt,
00181     const label nSweeps
00182 ) const
00183 {
00184     smooth
00185     (
00186         fieldName_,
00187         psi,
00188         matrix_,
00189         source,
00190         interfaceBouCoeffs_,
00191         interfaces_,
00192         cmpt,
00193         nSweeps
00194     );
00195 }
00196 
00197 
00198 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines