void Foam::DILUPreconditioner::precondition ( scalarField& wA, const scalarField& rA, const direction ) const { scalar* __restrict__ wAPtr = wA.begin(); const scalar* __restrict__ rAPtr = rA.begin(); const scalar* __restrict__ rDPtr = rD_.begin(); const label* const __restrict__ uPtr = matrix_.lduAddr().upperAddr().begin(); const label* const __restrict__ lPtr = matrix_.lduAddr().lowerAddr().begin(); const label* const __restrict__ losortPtr = matrix_.lduAddr().losortAddr().begin(); const scalar* const __restrict__ upperPtr = matrix_.upper().begin(); const scalar* const __restrict__ lowerPtr = matrix_.lower().begin(); register label nCells = wA.size(); register label nFaces = matrix_.upper().size(); register label nFacesM1 = nFaces - 1; for (register label cell=0; cell<nCells; cell++) { wAPtr[cell] = rDPtr[cell]*rAPtr[cell]; } register label sface; for (register label face=0; face<nFaces; face++) { sface = losortPtr[face]; wAPtr[uPtr[sface]] -= rDPtr[uPtr[sface]]*lowerPtr[sface]*wAPtr[lPtr[sface]]; } for (register label face=nFacesM1; face>=0; face--) { wAPtr[lPtr[face]] -= rDPtr[lPtr[face]]*upperPtr[face]*wAPtr[uPtr[face]]; } }
void Foam::noPreconditioner::precondition ( scalarField& wA, const scalarField& rA, const direction ) const { scalar* __restrict__ wAPtr = wA.begin(); const scalar* __restrict__ rAPtr = rA.begin(); register label nCells = wA.size(); for (register label cell=0; cell<nCells; cell++) { wAPtr[cell] = rAPtr[cell]; } }
void Foam::lduMatrix::Tmul ( scalarField& Tpsi, const tmp<scalarField>& tpsi, const FieldField<Field, scalar>& interfaceIntCoeffs, const lduInterfaceFieldPtrsList& interfaces, const direction cmpt ) const { scalar* __restrict__ TpsiPtr = Tpsi.begin(); const scalarField& psi = tpsi(); const scalar* const __restrict__ psiPtr = psi.begin(); const scalar* const __restrict__ diagPtr = diag().begin(); const label* const __restrict__ uPtr = lduAddr().upperAddr().begin(); const label* const __restrict__ lPtr = lduAddr().lowerAddr().begin(); const scalar* const __restrict__ lowerPtr = lower().begin(); const scalar* const __restrict__ upperPtr = upper().begin(); // Initialise the update of interfaced interfaces initMatrixInterfaces ( interfaceIntCoeffs, interfaces, psi, Tpsi, cmpt ); const label nCells = diag().size(); for (label cell=0; cell<nCells; cell++) { TpsiPtr[cell] = diagPtr[cell]*psiPtr[cell]; } const label nFaces = upper().size(); for (label face=0; face<nFaces; face++) { TpsiPtr[uPtr[face]] += upperPtr[face]*psiPtr[lPtr[face]]; TpsiPtr[lPtr[face]] += lowerPtr[face]*psiPtr[uPtr[face]]; } // Update interface interfaces updateMatrixInterfaces ( interfaceIntCoeffs, interfaces, psi, Tpsi, cmpt ); tpsi.clear(); }
void Foam::FDICPreconditioner::precondition ( scalarField& wA, const scalarField& rA, const direction ) const { scalar* __restrict__ wAPtr = wA.begin(); const scalar* __restrict__ rAPtr = rA.begin(); const scalar* __restrict__ rDPtr = rD_.begin(); const label* const __restrict__ uPtr = solver_.matrix().lduAddr().upperAddr().begin(); const label* const __restrict__ lPtr = solver_.matrix().lduAddr().lowerAddr().begin(); const scalar* const __restrict__ rDuUpperPtr = rDuUpper_.begin(); const scalar* const __restrict__ rDlUpperPtr = rDlUpper_.begin(); label nCells = wA.size(); label nFaces = solver_.matrix().upper().size(); label nFacesM1 = nFaces - 1; for (label cell=0; cell<nCells; cell++) { wAPtr[cell] = rDPtr[cell]*rAPtr[cell]; } for (label face=0; face<nFaces; face++) { wAPtr[uPtr[face]] -= rDuUpperPtr[face]*wAPtr[lPtr[face]]; } for (label face=nFacesM1; face>=0; face--) { wAPtr[lPtr[face]] -= rDlUpperPtr[face]*wAPtr[uPtr[face]]; } }
void Foam::lduMatrix::sumA ( scalarField& sumA, const FieldField<Field, scalar>& interfaceBouCoeffs, const lduInterfaceFieldPtrsList& interfaces ) const { scalar* __restrict__ sumAPtr = sumA.begin(); const scalar* __restrict__ diagPtr = diag().begin(); const label* __restrict__ uPtr = lduAddr().upperAddr().begin(); const label* __restrict__ lPtr = lduAddr().lowerAddr().begin(); const scalar* __restrict__ lowerPtr = lower().begin(); const scalar* __restrict__ upperPtr = upper().begin(); const label nCells = diag().size(); const label nFaces = upper().size(); for (label cell=0; cell<nCells; cell++) { sumAPtr[cell] = diagPtr[cell]; } for (label face=0; face<nFaces; face++) { sumAPtr[uPtr[face]] += lowerPtr[face]; sumAPtr[lPtr[face]] += upperPtr[face]; } // Add the interface internal coefficients to diagonal // and the interface boundary coefficients to the sum-off-diagonal forAll(interfaces, patchi) { if (interfaces.set(patchi)) { const labelUList& pa = lduAddr().patchAddr(patchi); const scalarField& pCoeffs = interfaceBouCoeffs[patchi]; forAll(pa, face) { sumAPtr[pa[face]] -= pCoeffs[face]; } } } }
Foam::lduMatrix::solverPerformance Foam::PCG::solve ( scalarField& psi, const scalarField& source, const direction cmpt ) const { // --- Setup class containing solver performance data lduMatrix::solverPerformance solverPerf ( lduMatrix::preconditioner::getName(controlDict_) + typeName, fieldName_ ); register label nCells = psi.size(); scalar* __restrict__ psiPtr = psi.begin(); scalarField pA(nCells); scalar* __restrict__ pAPtr = pA.begin(); scalarField wA(nCells); scalar* __restrict__ wAPtr = wA.begin(); scalar wArA = matrix_.great_; scalar wArAold = wArA; // --- Calculate A.psi matrix_.Amul(wA, psi, interfaceBouCoeffs_, interfaces_, cmpt); // --- Calculate initial residual field scalarField rA(source - wA); scalar* __restrict__ rAPtr = rA.begin(); // --- Calculate normalisation factor scalar normFactor = this->normFactor(psi, source, wA, pA); if (lduMatrix::debug >= 2) { Info<< " Normalisation factor = " << normFactor << endl; } // --- Calculate normalised residual norm solverPerf.initialResidual() = gSumMag(rA)/normFactor; solverPerf.finalResidual() = solverPerf.initialResidual(); // --- Check convergence, solve if not converged if (!solverPerf.checkConvergence(tolerance_, relTol_)) { // --- Select and construct the preconditioner autoPtr<lduMatrix::preconditioner> preconPtr = lduMatrix::preconditioner::New ( *this, controlDict_ ); // --- Solver iteration do { // --- Store previous wArA wArAold = wArA; // --- Precondition residual preconPtr->precondition(wA, rA, cmpt); // --- Update search directions: wArA = gSumProd(wA, rA); if (solverPerf.nIterations() == 0) { for (register label cell=0; cell<nCells; cell++) { pAPtr[cell] = wAPtr[cell]; } } else { scalar beta = wArA/wArAold; for (register label cell=0; cell<nCells; cell++) { pAPtr[cell] = wAPtr[cell] + beta*pAPtr[cell]; } } // --- Update preconditioned residual matrix_.Amul(wA, pA, interfaceBouCoeffs_, interfaces_, cmpt); scalar wApA = gSumProd(wA, pA); // --- Test for singularity if (solverPerf.checkSingularity(mag(wApA)/normFactor)) break; // --- Update solution and residual: scalar alpha = wArA/wApA; for (register label cell=0; cell<nCells; cell++) { psiPtr[cell] += alpha*pAPtr[cell]; rAPtr[cell] -= alpha*wAPtr[cell]; } solverPerf.finalResidual() = gSumMag(rA)/normFactor; } while ( solverPerf.nIterations()++ < maxIter_ && !(solverPerf.checkConvergence(tolerance_, relTol_)) ); } return solverPerf; }
Foam::solverPerformance Foam::PBiCGStab::solve ( scalarField& psi, const scalarField& source, const direction cmpt ) const { // --- Setup class containing solver performance data solverPerformance solverPerf ( lduMatrix::preconditioner::getName(controlDict_) + typeName, fieldName_ ); const label nCells = psi.size(); scalar* __restrict__ psiPtr = psi.begin(); scalarField pA(nCells); scalar* __restrict__ pAPtr = pA.begin(); scalarField yA(nCells); scalar* __restrict__ yAPtr = yA.begin(); // --- Calculate A.psi matrix_.Amul(yA, psi, interfaceBouCoeffs_, interfaces_, cmpt); // --- Calculate initial residual field scalarField rA(source - yA); scalar* __restrict__ rAPtr = rA.begin(); // --- Calculate normalisation factor const scalar normFactor = this->normFactor(psi, source, yA, pA); if (lduMatrix::debug >= 2) { Info<< " Normalisation factor = " << normFactor << endl; } // --- Calculate normalised residual norm solverPerf.initialResidual() = gSumMag(rA, matrix().mesh().comm()) /normFactor; solverPerf.finalResidual() = solverPerf.initialResidual(); // --- Check convergence, solve if not converged if ( minIter_ > 0 || !solverPerf.checkConvergence(tolerance_, relTol_) ) { scalarField AyA(nCells); scalar* __restrict__ AyAPtr = AyA.begin(); scalarField sA(nCells); scalar* __restrict__ sAPtr = sA.begin(); scalarField zA(nCells); scalar* __restrict__ zAPtr = zA.begin(); scalarField tA(nCells); scalar* __restrict__ tAPtr = tA.begin(); // --- Store initial residual const scalarField rA0(rA); // --- Initial values not used scalar rA0rA = 0; scalar alpha = 0; scalar omega = 0; // --- Select and construct the preconditioner autoPtr<lduMatrix::preconditioner> preconPtr = lduMatrix::preconditioner::New ( *this, controlDict_ ); // --- Solver iteration do { // --- Store previous rA0rA const scalar rA0rAold = rA0rA; rA0rA = gSumProd(rA0, rA, matrix().mesh().comm()); // --- Test for singularity if (solverPerf.checkSingularity(mag(rA0rA))) { break; } // --- Update pA if (solverPerf.nIterations() == 0) { for (label cell=0; cell<nCells; cell++) { pAPtr[cell] = rAPtr[cell]; } } else { // --- Test for singularity if (solverPerf.checkSingularity(mag(omega))) { break; } const scalar beta = (rA0rA/rA0rAold)*(alpha/omega); for (label cell=0; cell<nCells; cell++) { pAPtr[cell] = rAPtr[cell] + beta*(pAPtr[cell] - omega*AyAPtr[cell]); } } // --- Precondition pA preconPtr->precondition(yA, pA, cmpt); // --- Calculate AyA matrix_.Amul(AyA, yA, interfaceBouCoeffs_, interfaces_, cmpt); const scalar rA0AyA = gSumProd(rA0, AyA, matrix().mesh().comm()); alpha = rA0rA/rA0AyA; // --- Calculate sA for (label cell=0; cell<nCells; cell++) { sAPtr[cell] = rAPtr[cell] - alpha*AyAPtr[cell]; } // --- Test sA for convergence solverPerf.finalResidual() = gSumMag(sA, matrix().mesh().comm())/normFactor; if (solverPerf.checkConvergence(tolerance_, relTol_)) { for (label cell=0; cell<nCells; cell++) { psiPtr[cell] += alpha*yAPtr[cell]; } solverPerf.nIterations()++; return solverPerf; } // --- Precondition sA preconPtr->precondition(zA, sA, cmpt); // --- Calculate tA matrix_.Amul(tA, zA, interfaceBouCoeffs_, interfaces_, cmpt); const scalar tAtA = gSumSqr(tA, matrix().mesh().comm()); // --- Calculate omega from tA and sA // (cheaper than using zA with preconditioned tA) omega = gSumProd(tA, sA, matrix().mesh().comm())/tAtA; // --- Update solution and residual for (label cell=0; cell<nCells; cell++) { psiPtr[cell] += alpha*yAPtr[cell] + omega*zAPtr[cell]; rAPtr[cell] = sAPtr[cell] - omega*tAPtr[cell]; } solverPerf.finalResidual() = gSumMag(rA, matrix().mesh().comm()) /normFactor; } while ( ( solverPerf.nIterations()++ < maxIter_ && !solverPerf.checkConvergence(tolerance_, relTol_) ) || solverPerf.nIterations() < minIter_ ); } return solverPerf; }
void Foam::GaussSeidelSmoother::smooth ( const word& fieldName_, scalarField& psi, const lduMatrix& matrix_, const scalarField& source, const FieldField<Field, scalar>& interfaceBouCoeffs_, const lduInterfaceFieldPtrsList& interfaces_, const direction cmpt, const label nSweeps ) { register scalar* psiPtr = psi.begin(); register const label nCells = psi.size(); scalarField bPrime(nCells); register scalar* bPrimePtr = bPrime.begin(); register const scalar* const diagPtr = matrix_.diag().begin(); register const scalar* const upperPtr = matrix_.upper().begin(); register const scalar* const lowerPtr = matrix_.lower().begin(); register const label* const uPtr = matrix_.lduAddr().upperAddr().begin(); register const label* const ownStartPtr = matrix_.lduAddr().ownerStartAddr().begin(); // Parallel boundary initialisation. The parallel boundary is treated // as an effective jacobi interface in the boundary. // Note: there is a change of sign in the coupled // interface update. The reason for this is that the // internal coefficients are all located at the l.h.s. of // the matrix whereas the "implicit" coefficients on the // coupled boundaries are all created as if the // coefficient contribution is of a source-kind (i.e. they // have a sign as if they are on the r.h.s. of the matrix. // To compensate for this, it is necessary to turn the // sign of the contribution. FieldField<Field, scalar> mBouCoeffs(interfaceBouCoeffs_.size()); forAll(mBouCoeffs, patchi) { if (interfaces_.set(patchi)) { mBouCoeffs.set(patchi, -interfaceBouCoeffs_[patchi]); } } for (label sweep=0; sweep<nSweeps; sweep++) { bPrime = source; matrix_.initMatrixInterfaces ( mBouCoeffs, interfaces_, psi, bPrime, cmpt ); matrix_.updateMatrixInterfaces ( mBouCoeffs, interfaces_, psi, bPrime, cmpt ); register scalar curPsi; register label fStart; register label fEnd = ownStartPtr[0]; for (register label cellI=0; cellI<nCells; cellI++) { // Start and end of this row fStart = fEnd; fEnd = ownStartPtr[cellI + 1]; // Get the accumulated neighbour side curPsi = bPrimePtr[cellI]; // Accumulate the owner product side for (register label curFace=fStart; curFace<fEnd; curFace++) { curPsi -= upperPtr[curFace]*psiPtr[uPtr[curFace]]; } // Finish current psi curPsi /= diagPtr[cellI]; // Distribute the neighbour side using current psi for (register label curFace=fStart; curFace<fEnd; curFace++) { bPrimePtr[uPtr[curFace]] -= lowerPtr[curFace]*curPsi; } psiPtr[cellI] = curPsi; } } }
Foam::lduSolverPerformance Foam::PBiCG::solve ( scalarField& x, const scalarField& b, const direction cmpt ) const { // --- Setup class containing solver performance data lduSolverPerformance solverPerf ( lduMatrix::preconditioner::getName(dict()) + typeName, fieldName() ); register label nCells = x.size(); scalar* __restrict__ xPtr = x.begin(); scalarField pA(nCells); scalar* __restrict__ pAPtr = pA.begin(); scalarField pT(nCells, 0.0); scalar* __restrict__ pTPtr = pT.begin(); scalarField wA(nCells); scalar* __restrict__ wAPtr = wA.begin(); scalarField wT(nCells); scalar* __restrict__ wTPtr = wT.begin(); scalar wArT = matrix_.great_; scalar wArTold = wArT; // Calculate A.x and T.x matrix_.Amul(wA, x, coupleBouCoeffs_, interfaces_, cmpt); matrix_.Tmul(wT, x, coupleIntCoeffs_, interfaces_, cmpt); // Calculate initial residual and transpose residual fields scalarField rA(b - wA); scalarField rT(b - wT); scalar* __restrict__ rAPtr = rA.begin(); scalar* __restrict__ rTPtr = rT.begin(); // Calculate normalisation factor scalar normFactor = this->normFactor(x, b, wA, pA, cmpt); if (lduMatrix::debug >= 2) { Info<< " Normalisation factor = " << normFactor << endl; } // Calculate normalised residual norm solverPerf.initialResidual() = gSumMag(rA)/normFactor; solverPerf.finalResidual() = solverPerf.initialResidual(); // Check convergence, solve if not converged if (!stop(solverPerf)) { // Select and construct the preconditioner autoPtr<lduPreconditioner> preconPtr; preconPtr = lduPreconditioner::New ( matrix_, coupleBouCoeffs_, coupleIntCoeffs_, interfaces_, dict() ); // Solver iteration do { // Store previous wArT wArTold = wArT; // Precondition residuals preconPtr->precondition(wA, rA, cmpt); preconPtr->preconditionT(wT, rT, cmpt); // Update search directions: wArT = gSumProd(wA, rT); if (solverPerf.nIterations() == 0) { for (register label cell=0; cell<nCells; cell++) { pAPtr[cell] = wAPtr[cell]; pTPtr[cell] = wTPtr[cell]; } } else { scalar beta = wArT/wArTold; for (register label cell=0; cell<nCells; cell++) { pAPtr[cell] = wAPtr[cell] + beta*pAPtr[cell]; pTPtr[cell] = wTPtr[cell] + beta*pTPtr[cell]; } } // Update preconditioned residuals matrix_.Amul(wA, pA, coupleBouCoeffs_, interfaces_, cmpt); matrix_.Tmul(wT, pT, coupleIntCoeffs_, interfaces_, cmpt); scalar wApT = gSumProd(wA, pT); // Test for singularity if (solverPerf.checkSingularity(mag(wApT)/normFactor)) break; // Update solution and residual: scalar alpha = wArT/wApT; for (register label cell=0; cell<nCells; cell++) { xPtr[cell] += alpha*pAPtr[cell]; rAPtr[cell] -= alpha*wAPtr[cell]; rTPtr[cell] -= alpha*wTPtr[cell]; } solverPerf.finalResidual() = gSumMag(rA)/normFactor; solverPerf.nIterations()++; } while (!stop(solverPerf)); } return solverPerf; }
Foam::solverPerformance Foam::PBiCG::solve ( scalarField& psi, const scalarField& source, const direction cmpt ) const { // --- Setup class containing solver performance data solverPerformance solverPerf ( lduMatrix::preconditioner::getName(controlDict_) + typeName, fieldName_ ); label nCells = psi.size(); scalar* __restrict__ psiPtr = psi.begin(); scalarField pA(nCells); scalar* __restrict__ pAPtr = pA.begin(); scalarField pT(nCells, 0.0); scalar* __restrict__ pTPtr = pT.begin(); scalarField wA(nCells); scalar* __restrict__ wAPtr = wA.begin(); scalarField wT(nCells); scalar* __restrict__ wTPtr = wT.begin(); scalar wArT = solverPerf.great_; scalar wArTold = wArT; // --- Calculate A.psi and T.psi matrix_.Amul(wA, psi, interfaceBouCoeffs_, interfaces_, cmpt); matrix_.Tmul(wT, psi, interfaceIntCoeffs_, interfaces_, cmpt); // --- Calculate initial residual and transpose residual fields scalarField rA(source - wA); scalarField rT(source - wT); scalar* __restrict__ rAPtr = rA.begin(); scalar* __restrict__ rTPtr = rT.begin(); // --- Calculate normalisation factor scalar normFactor = this->normFactor(psi, source, wA, pA); if (lduMatrix::debug >= 2) { Info<< " Normalisation factor = " << normFactor << endl; } // --- Calculate normalised residual norm solverPerf.initialResidual() = gSumMag(rA, matrix().mesh().comm()) /normFactor; solverPerf.finalResidual() = solverPerf.initialResidual(); // --- Check convergence, solve if not converged if ( minIter_ > 0 || !solverPerf.checkConvergence(tolerance_, relTol_) ) { // --- Select and construct the preconditioner autoPtr<lduMatrix::preconditioner> preconPtr = lduMatrix::preconditioner::New ( *this, controlDict_ ); // --- Solver iteration do { // --- Store previous wArT wArTold = wArT; // --- Precondition residuals preconPtr->precondition(wA, rA, cmpt); preconPtr->preconditionT(wT, rT, cmpt); // --- Update search directions: wArT = gSumProd(wA, rT, matrix().mesh().comm()); if (solverPerf.nIterations() == 0) { for (label cell=0; cell<nCells; cell++) { pAPtr[cell] = wAPtr[cell]; pTPtr[cell] = wTPtr[cell]; } } else { scalar beta = wArT/wArTold; for (label cell=0; cell<nCells; cell++) { pAPtr[cell] = wAPtr[cell] + beta*pAPtr[cell]; pTPtr[cell] = wTPtr[cell] + beta*pTPtr[cell]; } } // --- Update preconditioned residuals matrix_.Amul(wA, pA, interfaceBouCoeffs_, interfaces_, cmpt); matrix_.Tmul(wT, pT, interfaceIntCoeffs_, interfaces_, cmpt); scalar wApT = gSumProd(wA, pT, matrix().mesh().comm()); // --- Test for singularity if (solverPerf.checkSingularity(mag(wApT)/normFactor)) { break; } // --- Update solution and residual: scalar alpha = wArT/wApT; for (label cell=0; cell<nCells; cell++) { psiPtr[cell] += alpha*pAPtr[cell]; rAPtr[cell] -= alpha*wAPtr[cell]; rTPtr[cell] -= alpha*wTPtr[cell]; } solverPerf.finalResidual() = gSumMag(rA, matrix().mesh().comm()) /normFactor; } while ( ( solverPerf.nIterations()++ < maxIter_ && !solverPerf.checkConvergence(tolerance_, relTol_) ) || solverPerf.nIterations() < minIter_ ); } return solverPerf; }
void Foam::symGaussSeidelPrecon::precondition ( scalarField& x, const scalarField& b, const direction cmpt ) const { // Execute preconditioning if (matrix_.diagonal()) { x = b/matrix_.diag(); } else if (matrix_.symmetric() || matrix_.asymmetric()) { scalar* __restrict__ xPtr = x.begin(); const scalar* __restrict__ diagPtr = matrix_.diag().begin(); scalar* __restrict__ bPrimePtr = bPrime_.begin(); const label* const __restrict__ uPtr = matrix_.lduAddr().upperAddr().begin(); const label* const __restrict__ ownStartPtr = matrix_.lduAddr().ownerStartAddr().begin(); const scalar* const __restrict__ lowerPtr = matrix_.lower().begin(); const scalar* const __restrict__ upperPtr = matrix_.upper().begin(); const label nRows = x.size(); label fStart, fEnd; bPrime_ = b; // Coupled boundary update { matrix_.initMatrixInterfaces ( coupleBouCoeffs_, interfaces_, x, bPrime_, cmpt, true // switch to lhs of system ); matrix_.updateMatrixInterfaces ( coupleBouCoeffs_, interfaces_, x, bPrime_, cmpt, true // switch to lhs of system ); } // Forward sweep for (register label rowI = 0; rowI < nRows; rowI++) { // lRow is equal to rowI scalar& curX = xPtr[rowI]; // Grab the accumulated neighbour side curX = bPrimePtr[rowI]; // Start and end of this row fStart = ownStartPtr[rowI]; fEnd = ownStartPtr[rowI + 1]; // Accumulate the owner product side for (register label curCoeff = fStart; curCoeff < fEnd; curCoeff++) { curX -= upperPtr[curCoeff]*xPtr[uPtr[curCoeff]]; } // Finish current x curX /= diagPtr[rowI]; // Distribute the neighbour side using current x for (register label curCoeff = fStart; curCoeff < fEnd; curCoeff++) { bPrimePtr[uPtr[curCoeff]] -= lowerPtr[curCoeff]*curX; } } // Reverse sweep for (register label rowI = nRows - 1; rowI >= 0; rowI--) { // lRow is equal to rowI scalar& curX = xPtr[rowI]; // Grab the accumulated neighbour side curX = bPrimePtr[rowI]; // Start and end of this row fStart = ownStartPtr[rowI]; fEnd = ownStartPtr[rowI + 1]; // Accumulate the owner product side for (register label curCoeff = fStart; curCoeff < fEnd; curCoeff++) { curX -= upperPtr[curCoeff]*xPtr[uPtr[curCoeff]]; } // Finish current x curX /= diagPtr[rowI]; // No need to update bPrime on reverse sweep. VV, 20/May/2015. } }
void Foam::symGaussSeidelSmoother::smooth ( const word& fieldName_, scalarField& psi, const lduMatrix& matrix_, const scalarField& source, const FieldField<Field, scalar>& interfaceBouCoeffs_, const lduInterfaceFieldPtrsList& interfaces_, const direction cmpt, const label nSweeps ) { scalar* __restrict__ psiPtr = psi.begin(); const label nCells = psi.size(); scalarField bPrime(nCells); scalar* __restrict__ bPrimePtr = bPrime.begin(); const scalar* const __restrict__ diagPtr = matrix_.diag().begin(); const scalar* const __restrict__ upperPtr = matrix_.upper().begin(); const scalar* const __restrict__ lowerPtr = matrix_.lower().begin(); const label* const __restrict__ uPtr = matrix_.lduAddr().upperAddr().begin(); const label* const __restrict__ ownStartPtr = matrix_.lduAddr().ownerStartAddr().begin(); // Parallel boundary initialisation. The parallel boundary is treated // as an effective jacobi interface in the boundary. // Note: there is a change of sign in the coupled // interface update. The reason for this is that the // internal coefficients are all located at the l.h.s. of // the matrix whereas the "implicit" coefficients on the // coupled boundaries are all created as if the // coefficient contribution is of a source-kind (i.e. they // have a sign as if they are on the r.h.s. of the matrix. // To compensate for this, it is necessary to turn the // sign of the contribution. FieldField<Field, scalar>& mBouCoeffs = const_cast<FieldField<Field, scalar>&> ( interfaceBouCoeffs_ ); forAll(mBouCoeffs, patchi) { if (interfaces_.set(patchi)) { mBouCoeffs[patchi].negate(); } } for (label sweep=0; sweep<nSweeps; sweep++) { bPrime = source; matrix_.initMatrixInterfaces ( mBouCoeffs, interfaces_, psi, bPrime, cmpt ); matrix_.updateMatrixInterfaces ( mBouCoeffs, interfaces_, psi, bPrime, cmpt ); scalar psii; label fStart; label fEnd = ownStartPtr[0]; for (label celli=0; celli<nCells; celli++) { // Start and end of this row fStart = fEnd; fEnd = ownStartPtr[celli + 1]; // Get the accumulated neighbour side psii = bPrimePtr[celli]; // Accumulate the owner product side for (label facei=fStart; facei<fEnd; facei++) { psii -= upperPtr[facei]*psiPtr[uPtr[facei]]; } // Finish current psi psii /= diagPtr[celli]; // Distribute the neighbour side using current psi for (label facei=fStart; facei<fEnd; facei++) { bPrimePtr[uPtr[facei]] -= lowerPtr[facei]*psii; } psiPtr[celli] = psii; } fStart = ownStartPtr[nCells]; for (label celli=nCells-1; celli>=0; celli--) { // Start and end of this row fEnd = fStart; fStart = ownStartPtr[celli]; // Get the accumulated neighbour side psii = bPrimePtr[celli]; // Accumulate the owner product side for (label facei=fStart; facei<fEnd; facei++) { psii -= upperPtr[facei]*psiPtr[uPtr[facei]]; } // Finish psi for this cell psii /= diagPtr[celli]; // Distribute the neighbour side using psi for this cell for (label facei=fStart; facei<fEnd; facei++) { bPrimePtr[uPtr[facei]] -= lowerPtr[facei]*psii; } psiPtr[celli] = psii; } } // Restore interfaceBouCoeffs_ forAll(mBouCoeffs, patchi) { if (interfaces_.set(patchi)) { mBouCoeffs[patchi].negate(); } } }
void Foam::FDICPreconditioner::precondition ( scalarField& wA, const scalarField& rA, const direction ) const { scalar* __restrict__ wAPtr = wA.begin(); const scalar* __restrict__ rAPtr = rA.begin(); const scalar* __restrict__ rDPtr = rD_.begin(); const label* const __restrict__ uPtr = matrix_.lduAddr().upperAddr().begin(); const label* const __restrict__ lPtr = matrix_.lduAddr().lowerAddr().begin(); const scalar* const __restrict__ rDuUpperPtr = rDuUpper_.begin(); const scalar* const __restrict__ rDlUpperPtr = rDlUpper_.begin(); register label nCells = wA.size(); register label nFaces = matrix_.upper().size(); register label nFacesM1 = nFaces - 1; #ifdef ICC_IA64_PREFETCH #pragma ivdep #endif for (register label cell=0; cell<nCells; cell++) { #ifdef ICC_IA64_PREFETCH __builtin_prefetch (&wAPtr[cell+96],0,1); __builtin_prefetch (&rDPtr[cell+96],0,1); __builtin_prefetch (&rAPtr[cell+96],0,1); #endif wAPtr[cell] = rDPtr[cell]*rAPtr[cell]; } #ifdef ICC_IA64_PREFETCH #pragma noprefetch uPtr,lPtr,rDuUpperPtr,wAPtr #pragma nounroll #endif for (register label face=0; face<nFaces; face++) { #ifdef ICC_IA64_PREFETCH __builtin_prefetch (&uPtr[face+96],0,0); __builtin_prefetch (&lPtr[face+96],0,0); __builtin_prefetch (&rDuUpperPtr[face+96],0,0); __builtin_prefetch (&wAPtr[uPtr[face+32]],0,1); __builtin_prefetch (&wAPtr[lPtr[face+32]],0,1); #endif wAPtr[uPtr[face]] -= rDuUpperPtr[face]*wAPtr[lPtr[face]]; } #ifdef ICC_IA64_PREFETCH #pragma noprefetch uPtr,lPtr,rDlUpperPtr,wAPtr #pragma nounroll #endif for (register label face=nFacesM1; face>=0; face--) { #ifdef ICC_IA64_PREFETCH __builtin_prefetch (&uPtr[face-95],0,0); __builtin_prefetch (&lPtr[face-95],0,0); __builtin_prefetch (&rDlUpperPtr[face-95],0,0); __builtin_prefetch (&wAPtr[lPtr[face-16]],0,1); __builtin_prefetch (&wAPtr[uPtr[face-16]],0,1); __builtin_prefetch (&wAPtr[lPtr[face-24]],0,1); __builtin_prefetch (&wAPtr[uPtr[face-24]],0,1); __builtin_prefetch (&wAPtr[lPtr[face-32]],0,1); __builtin_prefetch (&wAPtr[uPtr[face-32]],0,1); #endif wAPtr[lPtr[face]] -= rDlUpperPtr[face]*wAPtr[uPtr[face]]; } }
void Foam::lduMatrix::residual ( scalarField& rA, const scalarField& psi, const scalarField& source, const FieldField<Field, scalar>& interfaceBouCoeffs, const lduInterfaceFieldPtrsList& interfaces, const direction cmpt ) const { scalar* __restrict__ rAPtr = rA.begin(); const scalar* const __restrict__ psiPtr = psi.begin(); const scalar* const __restrict__ diagPtr = diag().begin(); const scalar* const __restrict__ sourcePtr = source.begin(); const label* const __restrict__ uPtr = lduAddr().upperAddr().begin(); const label* const __restrict__ lPtr = lduAddr().lowerAddr().begin(); const scalar* const __restrict__ upperPtr = upper().begin(); const scalar* const __restrict__ lowerPtr = lower().begin(); // Parallel boundary initialisation. // Note: there is a change of sign in the coupled // interface update. The reason for this is that the // internal coefficients are all located at the l.h.s. of // the matrix whereas the "implicit" coefficients on the // coupled boundaries are all created as if the // coefficient contribution is of a source-kind (i.e. they // have a sign as if they are on the r.h.s. of the matrix. // To compensate for this, it is necessary to turn the // sign of the contribution. FieldField<Field, scalar> mBouCoeffs(interfaceBouCoeffs.size()); forAll(mBouCoeffs, patchi) { if (interfaces.set(patchi)) { mBouCoeffs.set(patchi, -interfaceBouCoeffs[patchi]); } } // Initialise the update of interfaced interfaces initMatrixInterfaces ( mBouCoeffs, interfaces, psi, rA, cmpt ); const label nCells = diag().size(); for (label cell=0; cell<nCells; cell++) { rAPtr[cell] = sourcePtr[cell] - diagPtr[cell]*psiPtr[cell]; } const label nFaces = upper().size(); for (label face=0; face<nFaces; face++) { rAPtr[uPtr[face]] -= lowerPtr[face]*psiPtr[lPtr[face]]; rAPtr[lPtr[face]] -= upperPtr[face]*psiPtr[uPtr[face]]; } // Update interface interfaces updateMatrixInterfaces ( mBouCoeffs, interfaces, psi, rA, cmpt ); }