void Foam::GAMGPreconditioner::precondition ( scalarField& wA, const scalarField& rA, const direction cmpt ) const { wA = 0.0; scalarField AwA(wA.size()); scalarField finestCorrection(wA.size()); scalarField finestResidual(rA); // Create coarse grid correction fields PtrList<scalarField> coarseCorrX; // Create coarse grid sources PtrList<scalarField> coarseB; // Create the smoothers for all levels PtrList<lduSmoother> smoothers; // Initialise the above data structures GAMG_.initVcycle(coarseCorrX, coarseB, smoothers); for (label cycle=0; cycle<nVcycles_; cycle++) { GAMG_.Vcycle ( smoothers, wA, rA, AwA, finestCorrection, finestResidual, coarseCorrX, coarseB, cmpt ); if (cycle < nVcycles_ - 1) { // Calculate finest level residual field matrix_.Amul(AwA, wA, coupleBouCoeffs_, interfaces_, cmpt); finestResidual = rA; finestResidual -= AwA; } } }
void Foam::GAMGPreconditioner::precondition ( solveScalarField& wA, const solveScalarField& rA_ss, const direction cmpt ) const { wA = 0.0; solveScalarField AwA(wA.size()); solveScalarField finestCorrection(wA.size()); solveScalarField finestResidual(rA_ss); // Create coarse grid correction fields PtrList<solveScalarField> coarseCorrFields; // Create coarse grid sources PtrList<solveScalarField> 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 solveScalarField ApsiScratch; solveScalarField finestCorrectionScratch; // Initialise the above data structures initVcycle ( coarseCorrFields, coarseSources, smoothers, ApsiScratch, finestCorrectionScratch ); scalarField rA_s; for (label cycle=0; cycle<nVcycles_; cycle++) { const scalarField& rA = ConstFieldWrapper<scalar, solveScalar>::get(rA_ss, rA_s); Vcycle ( smoothers, wA, rA, AwA, finestCorrection, finestResidual, (ApsiScratch.size() ? ApsiScratch : AwA), ( finestCorrectionScratch.size() ? finestCorrectionScratch : finestCorrection ), coarseCorrFields, coarseSources, cmpt ); if (cycle < nVcycles_-1) { // Calculate finest level residual field matrix_.Amul(AwA, wA, interfaceBouCoeffs_, interfaces_, cmpt); finestResidual = rA_ss; finestResidual -= AwA; } } }
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; }