Foam::solverPerformance Foam::smoothSolver::solve ( scalarField& psi_s, const scalarField& source, const direction cmpt ) const { FieldWrapper<solveScalar, scalar> tpsi(psi_s); solveScalarField& psi = tpsi.constCast(); // Setup class containing solver performance data solverPerformance solverPerf(typeName, fieldName_); // If the nSweeps_ is negative do a fixed number of sweeps if (nSweeps_ < 0) { addProfiling(solve, "lduMatrix::smoother." + fieldName_); autoPtr<lduMatrix::smoother> smootherPtr = lduMatrix::smoother::New ( fieldName_, matrix_, interfaceBouCoeffs_, interfaceIntCoeffs_, interfaces_, controlDict_ ); smootherPtr->smooth ( psi, source, cmpt, -nSweeps_ ); solverPerf.nIterations() -= nSweeps_; } else { solveScalar normFactor = 0; solveScalarField residual; ConstFieldWrapper<solveScalar, scalar> tsource(source); { solveScalarField Apsi(psi.size()); solveScalarField temp(psi.size()); // Calculate A.psi matrix_.Amul(Apsi, psi, interfaceBouCoeffs_, interfaces_, cmpt); // Calculate normalisation factor normFactor = this->normFactor(psi, source, Apsi, temp); residual = tsource() - Apsi; matrix().setResidualField ( ConstFieldWrapper<scalar, solveScalar>(residual)(), fieldName_, false ); // Calculate residual magnitude solverPerf.initialResidual() = gSumMag(residual, matrix().mesh().comm())/normFactor; solverPerf.finalResidual() = solverPerf.initialResidual(); } if (lduMatrix::debug >= 2) { Info.masterStream(matrix().mesh().comm()) << " Normalisation factor = " << normFactor << endl; } // Check convergence, solve if not converged if ( minIter_ > 0 || !solverPerf.checkConvergence(tolerance_, relTol_) ) { addProfiling(solve, "lduMatrix::smoother." + fieldName_); autoPtr<lduMatrix::smoother> smootherPtr = lduMatrix::smoother::New ( fieldName_, matrix_, interfaceBouCoeffs_, interfaceIntCoeffs_, interfaces_, controlDict_ ); // Smoothing loop do { smootherPtr->smooth ( psi, source, cmpt, nSweeps_ ); residual = matrix_.residual ( psi, source, interfaceBouCoeffs_, interfaces_, cmpt ); // Calculate the residual to check convergence solverPerf.finalResidual() = gSumMag(residual, matrix().mesh().comm())/normFactor; } while ( ( (solverPerf.nIterations() += nSweeps_) < maxIter_ && !solverPerf.checkConvergence(tolerance_, relTol_) ) || solverPerf.nIterations() < minIter_ ); } matrix().setResidualField ( ConstFieldWrapper<scalar, solveScalar>(residual)(), fieldName_, false ); } return solverPerf; }
Foam::SolverPerformance<Type> Foam::SmoothSolver<Type, DType, LUType>::solve(Field<Type>& psi) const { // --- Setup class containing solver performance data SolverPerformance<Type> solverPerf ( typeName, this->fieldName_ ); label nIter = 0; // If the nSweeps_ is negative do a fixed number of sweeps if (nSweeps_ < 0) { autoPtr<typename LduMatrix<Type, DType, LUType>::smoother> smootherPtr = LduMatrix<Type, DType, LUType>::smoother::New ( this->fieldName_, this->matrix_, this->controlDict_ ); smootherPtr->smooth(psi, -nSweeps_); nIter -= nSweeps_; } else { Type normFactor = Zero; { Field<Type> Apsi(psi.size()); Field<Type> temp(psi.size()); // Calculate A.psi this->matrix_.Amul(Apsi, psi); // Calculate normalisation factor normFactor = this->normFactor(psi, Apsi, temp); // Calculate residual magnitude solverPerf.initialResidual() = cmptDivide ( gSumCmptMag(this->matrix_.source() - Apsi), normFactor ); solverPerf.finalResidual() = solverPerf.initialResidual(); } if (LduMatrix<Type, DType, LUType>::debug >= 2) { Info<< " Normalisation factor = " << normFactor << endl; } // Check convergence, solve if not converged if ( this->minIter_ > 0 || !solverPerf.checkConvergence(this->tolerance_, this->relTol_) ) { autoPtr<typename LduMatrix<Type, DType, LUType>::smoother> smootherPtr = LduMatrix<Type, DType, LUType>::smoother::New ( this->fieldName_, this->matrix_, this->controlDict_ ); // Smoothing loop do { smootherPtr->smooth ( psi, nSweeps_ ); // Calculate the residual to check convergence solverPerf.finalResidual() = cmptDivide ( gSumCmptMag(this->matrix_.residual(psi)), normFactor ); } while ( ( (nIter += nSweeps_) < this->maxIter_ && !solverPerf.checkConvergence(this->tolerance_, this->relTol_) ) || nIter < this->minIter_ ); } } solverPerf.nIterations() = pTraits<typename pTraits<Type>::labelType>::one*nIter; return solverPerf; }
Foam::solverPerformance Foam::GAMGSolver::solve ( scalargpuField& psi, const scalargpuField& source, const direction cmpt ) const { // Setup class containing solver performance data solverPerformance solverPerf(typeName, fieldName_); // Calculate A.psi used to calculate the initial residual scalargpuField Apsi(psi.size()); matrix_.Amul(Apsi, psi, interfaceBouCoeffs_, interfaces_, cmpt); // Create the storage for the finestCorrection which may be used as a // temporary in normFactor scalargpuField finestCorrection(psi.size()); // Calculate normalisation factor scalar normFactor = this->normFactor(psi, source, Apsi, finestCorrection); if (debug >= 2) { Pout<< " Normalisation factor = " << normFactor << endl; } // Calculate initial finest-grid residual field scalargpuField finestResidual(source - Apsi); // Calculate normalised residual for convergence test solverPerf.initialResidual() = gSumMag ( finestResidual, matrix().mesh().comm() )/normFactor; solverPerf.finalResidual() = solverPerf.initialResidual(); // Check convergence, solve if not converged if ( minIter_ > 0 || !solverPerf.checkConvergence(tolerance_, relTol_) ) { // Create coarse grid correction fields PtrList<scalargpuField> coarseCorrFields; // Create coarse grid sources PtrList<scalargpuField> coarseSources; // Create the smoothers for all levels PtrList<lduMatrix::smoother> smoothers; // Scratch fields if processor-agglomerated coarse level meshes // are bigger than original. Usually not needed scalargpuField scratch1; scalargpuField scratch2; // Initialise the above data structures initVcycle ( coarseCorrFields, coarseSources, smoothers, scratch1, scratch2 ); do { Vcycle ( smoothers, psi, source, Apsi, finestCorrection, finestResidual, (scratch1.size() ? scratch1 : Apsi), (scratch2.size() ? scratch2 : finestCorrection), coarseCorrFields, coarseSources, cmpt ); // Calculate finest level residual field matrix_.Amul(Apsi, psi, interfaceBouCoeffs_, interfaces_, cmpt); finestResidual = source; finestResidual -= Apsi; solverPerf.finalResidual() = gSumMag ( finestResidual, matrix().mesh().comm() )/normFactor; if (debug >= 2) { solverPerf.print(Info.masterStream(matrix().mesh().comm())); } } while ( ( ++solverPerf.nIterations() < maxIter_ && !solverPerf.checkConvergence(tolerance_, relTol_) ) || solverPerf.nIterations() < minIter_ ); } return solverPerf; }