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

PBiCG.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/PBiCG.H>
00027 
00028 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
00029 
00030 namespace Foam
00031 {
00032     defineTypeNameAndDebug(PBiCG, 0);
00033 
00034     lduMatrix::solver::addasymMatrixConstructorToTable<PBiCG>
00035         addPBiCGAsymMatrixConstructorToTable_;
00036 }
00037 
00038 
00039 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
00040 
00041 Foam::PBiCG::PBiCG
00042 (
00043     const word& fieldName,
00044     const lduMatrix& matrix,
00045     const FieldField<Field, scalar>& interfaceBouCoeffs,
00046     const FieldField<Field, scalar>& interfaceIntCoeffs,
00047     const lduInterfaceFieldPtrsList& interfaces,
00048     const dictionary& solverControls
00049 )
00050 :
00051     lduMatrix::solver
00052     (
00053         fieldName,
00054         matrix,
00055         interfaceBouCoeffs,
00056         interfaceIntCoeffs,
00057         interfaces,
00058         solverControls
00059     )
00060 {}
00061 
00062 
00063 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
00064 
00065 Foam::lduMatrix::solverPerformance Foam::PBiCG::solve
00066 (
00067     scalarField& psi,
00068     const scalarField& source,
00069     const direction cmpt
00070 ) const
00071 {
00072     // --- Setup class containing solver performance data
00073     lduMatrix::solverPerformance solverPerf
00074     (
00075         lduMatrix::preconditioner::getName(controlDict_) + typeName,
00076         fieldName_
00077     );
00078 
00079     register label nCells = psi.size();
00080 
00081     scalar* __restrict__ psiPtr = psi.begin();
00082 
00083     scalarField pA(nCells);
00084     scalar* __restrict__ pAPtr = pA.begin();
00085 
00086     scalarField pT(nCells, 0.0);
00087     scalar* __restrict__ pTPtr = pT.begin();
00088 
00089     scalarField wA(nCells);
00090     scalar* __restrict__ wAPtr = wA.begin();
00091 
00092     scalarField wT(nCells);
00093     scalar* __restrict__ wTPtr = wT.begin();
00094 
00095     scalar wArT = matrix_.great_;
00096     scalar wArTold = wArT;
00097 
00098     // --- Calculate A.psi and T.psi
00099     matrix_.Amul(wA, psi, interfaceBouCoeffs_, interfaces_, cmpt);
00100     matrix_.Tmul(wT, psi, interfaceIntCoeffs_, interfaces_, cmpt);
00101 
00102     // --- Calculate initial residual and transpose residual fields
00103     scalarField rA(source - wA);
00104     scalarField rT(source - wT);
00105     scalar* __restrict__ rAPtr = rA.begin();
00106     scalar* __restrict__ rTPtr = rT.begin();
00107 
00108     // --- Calculate normalisation factor
00109     scalar normFactor = this->normFactor(psi, source, wA, pA);
00110 
00111     if (lduMatrix::debug >= 2)
00112     {
00113         Info<< "   Normalisation factor = " << normFactor << endl;
00114     }
00115 
00116     // --- Calculate normalised residual norm
00117     solverPerf.initialResidual() = gSumMag(rA)/normFactor;
00118     solverPerf.finalResidual() = solverPerf.initialResidual();
00119 
00120     // --- Check convergence, solve if not converged
00121     if (!solverPerf.checkConvergence(tolerance_, relTol_))
00122     {
00123         // --- Select and construct the preconditioner
00124         autoPtr<lduMatrix::preconditioner> preconPtr =
00125         lduMatrix::preconditioner::New
00126         (
00127             *this,
00128             controlDict_
00129         );
00130 
00131         // --- Solver iteration
00132         do
00133         {
00134             // --- Store previous wArT
00135             wArTold = wArT;
00136 
00137             // --- Precondition residuals
00138             preconPtr->precondition(wA, rA, cmpt);
00139             preconPtr->preconditionT(wT, rT, cmpt);
00140 
00141             // --- Update search directions:
00142             wArT = gSumProd(wA, rT);
00143 
00144             if (solverPerf.nIterations() == 0)
00145             {
00146                 for (register label cell=0; cell<nCells; cell++)
00147                 {
00148                     pAPtr[cell] = wAPtr[cell];
00149                     pTPtr[cell] = wTPtr[cell];
00150                 }
00151             }
00152             else
00153             {
00154                 scalar beta = wArT/wArTold;
00155 
00156                 for (register label cell=0; cell<nCells; cell++)
00157                 {
00158                     pAPtr[cell] = wAPtr[cell] + beta*pAPtr[cell];
00159                     pTPtr[cell] = wTPtr[cell] + beta*pTPtr[cell];
00160                 }
00161             }
00162 
00163 
00164             // --- Update preconditioned residuals
00165             matrix_.Amul(wA, pA, interfaceBouCoeffs_, interfaces_, cmpt);
00166             matrix_.Tmul(wT, pT, interfaceIntCoeffs_, interfaces_, cmpt);
00167 
00168             scalar wApT = gSumProd(wA, pT);
00169 
00170 
00171             // --- Test for singularity
00172             if (solverPerf.checkSingularity(mag(wApT)/normFactor)) break;
00173 
00174 
00175             // --- Update solution and residual:
00176 
00177             scalar alpha = wArT/wApT;
00178 
00179             for (register label cell=0; cell<nCells; cell++)
00180             {
00181                 psiPtr[cell] += alpha*pAPtr[cell];
00182                 rAPtr[cell] -= alpha*wAPtr[cell];
00183                 rTPtr[cell] -= alpha*wTPtr[cell];
00184             }
00185 
00186             solverPerf.finalResidual() = gSumMag(rA)/normFactor;
00187 
00188         } while
00189         (
00190             solverPerf.nIterations()++ < maxIter_
00191         && !(solverPerf.checkConvergence(tolerance_, relTol_))
00192         );
00193     }
00194 
00195     return solverPerf;
00196 }
00197 
00198 
00199 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines