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