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; }
Foam::SolverPerformance<Type> Foam::PBiCCCG<Type, DType, LUType>::solve ( Field<Type>& psi ) const { word preconditionerName(this->controlDict_.lookup("preconditioner")); // --- Setup class containing solver performance data SolverPerformance<Type> solverPerf ( preconditionerName + typeName, this->fieldName_ ); label nCells = psi.size(); Type* __restrict__ psiPtr = psi.begin(); Field<Type> pA(nCells); Type* __restrict__ pAPtr = pA.begin(); Field<Type> pT(nCells, Zero); Type* __restrict__ pTPtr = pT.begin(); Field<Type> wA(nCells); Type* __restrict__ wAPtr = wA.begin(); Field<Type> wT(nCells); Type* __restrict__ wTPtr = wT.begin(); scalar wArT = 1e15; //this->matrix_.great_; scalar wArTold = wArT; // --- Calculate A.psi and T.psi this->matrix_.Amul(wA, psi); this->matrix_.Tmul(wT, psi); // --- Calculate initial residual and transpose residual fields Field<Type> rA(this->matrix_.source() - wA); Field<Type> rT(this->matrix_.source() - wT); Type* __restrict__ rAPtr = rA.begin(); Type* __restrict__ rTPtr = rT.begin(); // --- Calculate normalisation factor Type normFactor = this->normFactor(psi, wA, pA); if (LduMatrix<Type, DType, LUType>::debug >= 2) { Info<< " Normalisation factor = " << normFactor << endl; } // --- Calculate normalised residual norm solverPerf.initialResidual() = cmptDivide(gSumCmptMag(rA), normFactor); solverPerf.finalResidual() = solverPerf.initialResidual(); // --- Check convergence, solve if not converged if ( this->minIter_ > 0 || !solverPerf.checkConvergence(this->tolerance_, this->relTol_) ) { // --- Select and construct the preconditioner autoPtr<typename LduMatrix<Type, DType, LUType>::preconditioner> preconPtr = LduMatrix<Type, DType, LUType>::preconditioner::New ( *this, this->controlDict_ ); // --- Solver iteration do { // --- Store previous wArT wArTold = wArT; // --- Precondition residuals preconPtr->precondition(wA, rA); preconPtr->preconditionT(wT, rT); // --- Update search directions: wArT = gSumProd(wA, rT); 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 this->matrix_.Amul(wA, pA); this->matrix_.Tmul(wT, pT); scalar wApT = gSumProd(wA, pT); // --- Test for singularity if ( solverPerf.checkSingularity ( cmptDivide(pTraits<Type>::one*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() = cmptDivide(gSumCmptMag(rA), normFactor); } while ( ( solverPerf.nIterations()++ < this->maxIter_ && !solverPerf.checkConvergence(this->tolerance_, this->relTol_) ) || solverPerf.nIterations() < this->minIter_ ); } return solverPerf; }
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; }
Foam::SolverPerformance<Type> Foam::PBiCCCG<Type, DType, LUType>::solve ( gpuField<Type>& psi ) const { word preconditionerName(this->controlDict_.lookup("preconditioner")); // --- Setup class containing solver performance data SolverPerformance<Type> solverPerf ( preconditionerName + typeName, this->fieldName_ ); register label nCells = psi.size(); gpuField<Type> pA(nCells); gpuField<Type> pT(nCells, pTraits<Type>::zero); gpuField<Type> wA(nCells); gpuField<Type> wT(nCells); scalar wArT = 1e15; //this->matrix_.great_; scalar wArTold = wArT; // --- Calculate A.psi and T.psi this->matrix_.Amul(wA, psi); this->matrix_.Tmul(wT, psi); // --- Calculate initial residual and transpose residual fields gpuField<Type> rA(this->matrix_.source() - wA); gpuField<Type> rT(this->matrix_.source() - wT); // --- Calculate normalisation factor Type normFactor = this->normFactor(psi, wA, pA); if (LduMatrix<Type, DType, LUType>::debug >= 2) { Info<< " Normalisation factor = " << normFactor << endl; } // --- Calculate normalised residual norm solverPerf.initialResidual() = cmptDivide(gSumCmptMag(rA), normFactor); solverPerf.finalResidual() = solverPerf.initialResidual(); // --- Check convergence, solve if not converged if ( this->minIter_ > 0 || !solverPerf.checkConvergence(this->tolerance_, this->relTol_) ) { // --- Select and construct the preconditioner autoPtr<typename LduMatrix<Type, DType, LUType>::preconditioner> preconPtr = LduMatrix<Type, DType, LUType>::preconditioner::New ( *this, this->controlDict_ ); // --- Solver iteration do { // --- Store previous wArT wArTold = wArT; // --- Precondition residuals preconPtr->precondition(wA, rA); preconPtr->preconditionT(wT, rT); // --- Update search directions: wArT = gSumProd(wA, rT); if (solverPerf.nIterations() == 0) { thrust::copy(wA.begin(),wA.end(),pA.begin()); thrust::copy(wT.begin(),wT.end(),pT.begin()); } else { scalar beta = wArT/wArTold; thrust::transform ( wA.begin(), wA.end(), thrust::make_transform_iterator ( pA.begin(), multiplyOperatorSFFunctor<scalar,Type,Type>(beta) ), pA.begin(), addOperatorFunctor<Type,Type,Type>() ); thrust::transform ( wT.begin(), wT.end(), thrust::make_transform_iterator ( pT.begin(), multiplyOperatorSFFunctor<scalar,Type,Type>(beta) ), pT.begin(), addOperatorFunctor<Type,Type,Type>() ); } // --- Update preconditioned residuals this->matrix_.Amul(wA, pA); this->matrix_.Tmul(wT, pT); scalar wApT = gSumProd(wA, pT); // --- Test for singularity if ( solverPerf.checkSingularity ( cmptDivide(pTraits<Type>::one*mag(wApT), normFactor) ) ) { break; } // --- Update solution and residual: scalar alpha = wArT/wApT; thrust::transform ( psi.begin(), psi.end(), thrust::make_transform_iterator ( pA.begin(), multiplyOperatorSFFunctor<scalar,Type,Type>(alpha) ), psi.begin(), addOperatorFunctor<Type,Type,Type>() ); thrust::transform ( rA.begin(), rA.end(), thrust::make_transform_iterator ( wA.begin(), multiplyOperatorSFFunctor<scalar,Type,Type>(alpha) ), rA.begin(), subtractOperatorFunctor<Type,Type,Type>() ); thrust::transform ( rT.begin(), rT.end(), thrust::make_transform_iterator ( wT.begin(), multiplyOperatorSFFunctor<scalar,Type,Type>(alpha) ), rT.begin(), subtractOperatorFunctor<Type,Type,Type>() ); solverPerf.finalResidual() = cmptDivide(gSumCmptMag(rA), normFactor); } while ( ( solverPerf.nIterations()++ < this->maxIter_ && !solverPerf.checkConvergence(this->tolerance_, this->relTol_) ) || solverPerf.nIterations() < this->minIter_ ); } return solverPerf; }