From 33936ac3bf8456bade7a089ceb83cdcfa64dc0b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Offringa?= <offringa@astron.nl> Date: Tue, 21 Aug 2018 20:26:10 +0000 Subject: [PATCH] Task #11550: Further improved the convergence criterion. It is now (finally) completely scale independent and uses a fully squared metric to upweight larger errors somewhat. --- CEP/DP3/DPPP_DDECal/src/MultiDirSolver.cc | 37 +++++++++++++++++------ 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/CEP/DP3/DPPP_DDECal/src/MultiDirSolver.cc b/CEP/DP3/DPPP_DDECal/src/MultiDirSolver.cc index 628f1a91798..61e121e3a7d 100644 --- a/CEP/DP3/DPPP_DDECal/src/MultiDirSolver.cc +++ b/CEP/DP3/DPPP_DDECal/src/MultiDirSolver.cc @@ -114,29 +114,46 @@ bool MultiDirSolver::assignSolutions(std::vector<std::vector<DComplex> >& soluti n += solutions[chBlock].size(); for(size_t i=0; i!=solutions[chBlock].size(); i += NPol) { - double nextSum, solSum; + // A normalized squared difference is calculated between the solutions of this + // and the previous step: + // sqrt { 1/n sum over | (t1 - t0) t0^(-1) |_2 } + // This criterion is scale independent: all solutions can be scaled without + // affecting the number of iterations. Also, when the polarized version is given + // scalar matrices, it will use the same number of iterations as the scalar + // version. if(NPol == 1) { - solSum = std::abs(solutions[chBlock][i]); - nextSum = std::norm(nextSolutions[chBlock][i] - solutions[chBlock][i]); + if(solutions[chBlock][i] != 0.0) + avgSquaredDiff += std::norm((nextSolutions[chBlock][i] - solutions[chBlock][i]) / solutions[chBlock][i]); solutions[chBlock][i] = nextSolutions[chBlock][i]; } else { - solSum = std::abs(solutions[chBlock][i]) + std::abs(solutions[chBlock][i+3]); - nextSum = 0.0; + MC2x2 s(&solutions[chBlock][i]), sInv(s); + if(sInv.Invert()) + { + MC2x2 n(&nextSolutions[chBlock][i]); + n -= s; + n *= sInv; + for(size_t p=0; p!=NPol; ++p) + avgSquaredDiff += std::norm(n[p]); + } for(size_t p=0; p!=NPol; ++p) { - nextSum += std::norm(nextSolutions[chBlock][i+p] - solutions[chBlock][i+p]); solutions[chBlock][i+p] = nextSolutions[chBlock][i+p]; } } - if(solSum != 0.0) - avgSquaredDiff += nextSum/solSum; } } - avgSquaredDiff /= n; + // The polarized version needs a factor of two normalization to make it work + // like the scalar version would and when given only scalar matrices. + if(NPol == 4) + avgSquaredDiff = sqrt(avgSquaredDiff*0.5/n) ; + else + avgSquaredDiff = sqrt(avgSquaredDiff/n); - double stepMagnitude = sqrt(avgSquaredDiff)/_stepSize; + // The stepsize is taken out, so that a small stepsize won't cause + // premiture succesful stopping criterion. + double stepMagnitude = avgSquaredDiff/_stepSize; stepMagnitudes.push_back(stepMagnitude); if(useConstraintAccuracy) -- GitLab