void Foam::steadyStateControl::maxTypeResidual ( const word& fieldName, ITstream& data, scalar& firstRes, scalar& lastRes ) const { typedef GeometricField<Type, fvPatchField, volMesh> fieldType; if (mesh_.foundObject<fieldType>(fieldName)) { //fieldType& pointVelocity = const_cast<fieldType&>( // mesh_.objectRegistry::lookupObject<fieldType>( fieldName ) //); fieldType& field = const_cast<fieldType&>( mesh_.lookupObject<fieldType>( fieldName ) ); const List<SolverPerformance<Type> > sp(data); int sz = field.size(); reduce(sz, sumOp<int>()); Type nF = gSumCmptProd( field, field ) / static_cast<double>(sz); //Type finiR = sp.first().initialResidual(); //Type liniR = sp.last().initialResidual(); // scalar norm = mag(nF); for (direction cmpt=0; cmpt < nF.size(); cmpt++){ nF[cmpt] = sqrt( nF[cmpt] ); //finiR[cmpt] *= tmpNF; //liniR[cmpt] *= tmpNF; } nF = nF/norm; //finiR /= norm; //liniR /= norm; //firstRes = cmptMax(finiR); //lastRes = cmptMax(liniR); // firstRes = cmptMax( cmptMultiply(sp.first().initialResidual(), nF) ); lastRes = cmptMax( cmptMultiply(sp.last().initialResidual(), nF) ); //firstRes = cmptMax(sp.first().initialResidual()); //lastRes = cmptMax(sp.last().initialResidual()); } }
typename Foam::SolverPerformance<Type> Foam::PCICG<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> wA(nCells); Type* __restrict__ wAPtr = wA.begin(); Type wArA = solverPerf.great_*pTraits<Type>::one; Type wArAold = wArA; // --- Calculate A.psi this->matrix_.Amul(wA, psi); // --- Calculate initial residual field Field<Type> rA(this->matrix_.source() - wA); Type* __restrict__ rAPtr = rA.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 wArA wArAold = wArA; // --- Precondition residual preconPtr->precondition(wA, rA); // --- Update search directions: wArA = gSumCmptProd(wA, rA); if (solverPerf.nIterations() == 0) { for (label cell=0; cell<nCells; cell++) { pAPtr[cell] = wAPtr[cell]; } } else { Type beta = cmptDivide ( wArA, stabilise(wArAold, solverPerf.vsmall_) ); for (label cell=0; cell<nCells; cell++) { pAPtr[cell] = wAPtr[cell] + cmptMultiply(beta, pAPtr[cell]); } } // --- Update preconditioned residual this->matrix_.Amul(wA, pA); Type wApA = gSumCmptProd(wA, pA); // --- Test for singularity if ( solverPerf.checkSingularity ( cmptDivide(cmptMag(wApA), normFactor) ) ) { break; } // --- Update solution and residual: Type alpha = cmptDivide ( wArA, stabilise(wApA, solverPerf.vsmall_) ); for (label cell=0; cell<nCells; cell++) { psiPtr[cell] += cmptMultiply(alpha, pAPtr[cell]); rAPtr[cell] -= cmptMultiply(alpha, wAPtr[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::SolverPerformance<Type> Foam::PBiCICG<Type, DType, LUType>::solve(gpuField<Type>& psi) const { word preconditionerName(this->controlDict_.lookup("preconditioner")); if(preconditionerName != "none") preconditionerName = "diagonal"; // --- 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); Type wArT = solverPerf.great_*pTraits<Type>::one; Type 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 (!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 = gSumCmptProd(wA, rT); if (solverPerf.nIterations() == 0) { thrust::copy(wA.begin(),wA.end(),pA.begin()); thrust::copy(wT.begin(),wT.end(),pT.begin()); } else { Type beta = cmptDivide ( wArT, stabilise(wArTold, solverPerf.vsmall_) ); thrust::transform ( wA.begin(), wA.end(), thrust::make_transform_iterator ( pA.begin(), cmptMultiplyBinaryFunctionSFFunctor<Type,Type,Type>(beta) ), pA.begin(), addOperatorFunctor<Type,Type,Type>() ); thrust::transform ( wT.begin(), wT.end(), thrust::make_transform_iterator ( pT.begin(), cmptMultiplyBinaryFunctionSFFunctor<Type,Type,Type>(beta) ), pT.begin(), addOperatorFunctor<Type,Type,Type>() ); } // --- Update preconditioned residuals this->matrix_.Amul(wA, pA); this->matrix_.Tmul(wT, pT); Type wApT = gSumCmptProd(wA, pT); // --- Test for singularity if ( solverPerf.checkSingularity ( cmptDivide(cmptMag(wApT), normFactor) ) ) { break; } // --- Update solution and residual: Type alpha = cmptDivide ( wArT, stabilise(wApT, solverPerf.vsmall_) ); thrust::transform ( psi.begin(), psi.end(), thrust::make_transform_iterator ( pA.begin(), cmptMultiplyBinaryFunctionSFFunctor<Type,Type,Type>(alpha) ), psi.begin(), addOperatorFunctor<Type,Type,Type>() ); thrust::transform ( rA.begin(), rA.end(), thrust::make_transform_iterator ( wA.begin(), cmptMultiplyBinaryFunctionSFFunctor<Type,Type,Type>(alpha) ), rA.begin(), subtractOperatorFunctor<Type,Type,Type>() ); thrust::transform ( rT.begin(), rT.end(), thrust::make_transform_iterator ( wT.begin(), cmptMultiplyBinaryFunctionSFFunctor<Type,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_)) ); } return solverPerf; }