public void UpdateResidual(CGAlgorithm cg, IVector residual, out double resDotRes) { // Update the residual vector normally: r = r - α * A*d residual.AxpyIntoThis(cg.MatrixTimesDirection, -cg.StepSize); resDotRes = residual.DotProduct(residual); //TODO: it is weird that this sets resDotRes and cg.ResDotRes // Check if the CG will converge. TODO: Remove duplicate comutations: this check will also be done by CG later. double residualNormRatio = convergence.EstimateResidualNormRatio(cg); // let's pray that ICGResidualConvergence does not mutate any fields bool hasConverged = residualNormRatio <= residualTolerance; // Avoid premature convergence by calculating th exact residual. if (hasConverged) { // Exact residual: r = b - A * x ExactResidual.Calculate(cg.Matrix, cg.Rhs, cg.Solution, residual); // Recalculate the r * r resDotRes = residual.DotProduct(residual); } }
/// <summary> /// See <see cref="ICGResidualUpdater.UpdateResidual(CGAlgorithm, IVector, out double)"/> /// </summary> public void UpdateResidual(CGAlgorithm cg, IVector residual, out double resDotRes) { //TODO: perhaps this should be done in an Initialize() method if (numIterationsBeforeCorrection == int.MinValue) { numIterationsBeforeCorrection = (int)Math.Floor(Math.Sqrt(cg.Rhs.Length)); } if ((cg.Iteration % numIterationsBeforeCorrection == 0) && (cg.Iteration != 0)) //The first iteration uses the correct residual. { // Calculate the exact residual: r = b - A * x ExactResidual.Calculate(cg.Matrix, cg.Rhs, cg.Solution, residual); } else { // Normally the residual vector is updated as: r = r - α * A*d residual.AxpyIntoThis(cg.MatrixTimesDirection, -cg.StepSize); } resDotRes = residual.DotProduct(residual); }
/// <summary> /// See <see cref="ICGResidualConvergence.Initialize(CGAlgorithm)"/> /// </summary> public void Initialize(CGAlgorithm cg) => this.residualNormInitial = Math.Sqrt(cg.ResDotRes);
/// <summary> /// See <see cref="ICGResidualUpdater.UpdateResidual(CGAlgorithm, IVector, out double)"/> /// </summary> public void UpdateResidual(CGAlgorithm cg, IVector residual, out double resDotRes) { // Normally the residual vector is updated as: r = r - α * A*d residual.AxpyIntoThis(cg.MatrixTimesDirection, -cg.StepSize); resDotRes = residual.DotProduct(residual); }
/// <summary> /// See <see cref="ICGResidualConvergence.EstimateResidualNormRatio(CGAlgorithm)"/> /// </summary> public double EstimateResidualNormRatio(CGAlgorithm cg) => Math.Sqrt(cg.ResDotRes) / residualNormInitial;