00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 #include <OpenFOAM/PBiCG.H>
00027 
00028 
00029 
00030 namespace Foam
00031 {
00032     defineTypeNameAndDebug(PBiCG, 0);
00033 
00034     lduMatrix::solver::addasymMatrixConstructorToTable<PBiCG>
00035         addPBiCGAsymMatrixConstructorToTable_;
00036 }
00037 
00038 
00039 
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 
00064 
00065 Foam::lduMatrix::solverPerformance Foam::PBiCG::solve
00066 (
00067     scalarField& psi,
00068     const scalarField& source,
00069     const direction cmpt
00070 ) const
00071 {
00072     
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     
00099     matrix_.Amul(wA, psi, interfaceBouCoeffs_, interfaces_, cmpt);
00100     matrix_.Tmul(wT, psi, interfaceIntCoeffs_, interfaces_, cmpt);
00101 
00102     
00103     scalarField rA(source - wA);
00104     scalarField rT(source - wT);
00105     scalar* __restrict__ rAPtr = rA.begin();
00106     scalar* __restrict__ rTPtr = rT.begin();
00107 
00108     
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     
00117     solverPerf.initialResidual() = gSumMag(rA)/normFactor;
00118     solverPerf.finalResidual() = solverPerf.initialResidual();
00119 
00120     
00121     if (!solverPerf.checkConvergence(tolerance_, relTol_))
00122     {
00123         
00124         autoPtr<lduMatrix::preconditioner> preconPtr =
00125         lduMatrix::preconditioner::New
00126         (
00127             *this,
00128             controlDict_
00129         );
00130 
00131         
00132         do
00133         {
00134             
00135             wArTold = wArT;
00136 
00137             
00138             preconPtr->precondition(wA, rA, cmpt);
00139             preconPtr->preconditionT(wT, rT, cmpt);
00140 
00141             
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             
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             
00172             if (solverPerf.checkSingularity(mag(wApT)/normFactor)) break;
00173 
00174 
00175             
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