Refinement: a B factor is held at its bound by the whole target's gradient, restraints included

The held test read the X-ray gradient alone. At the floor, an atom whose X-ray term pushed
outward but whose restraints pulled it back in more strongly was held fixed against the total
target, and one whose restraints pushed it out was handed a gradient along the direction Set()
clamps away - a flat direction for L-BFGS, failed line searches and s.y <= 0 pairs.

On the 14 parity sets (--mode refine, GPU) the refined models are md5-identical; on the four
5f6m MD starts R-free 0.1707/0.1676/0.1720/0.1669 -> 0.1707/0.1690/0.1719/0.1668 (median
0.1692 -> 0.1699).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015CeEGgpKdfkCTJb3YNMJcu
(cherry picked from commit 2f4b0b5ea54fdac54de7ee6c5a1476d2fc019fd8)
This commit is contained in:
leonarski_f committed 2026-10-26 15:38:59 +01:00
1 parent 2be88e11e3
commit 13bd9db55c
1 file changed
+4 -3
@@ -540,9 +540,10 @@ public:
for (int c = 0; c < 3; c++)
gradient[3 * k + c] = weight_ * gx[i][c] + gr[i][c];
else {
// held at a bound, B does not move further out
const bool held = (p[k] <= ctx_.b_floor && gx[i][3] > 0) || (p[k] >= ctx_.b_ceiling && gx[i][3] < 0);
gradient[k] = held ? 0.0 : weight_ * gx[i][3] + gr[i][3];
// held at a bound, B does not move further out: by the whole target, restraints included
const double g = weight_ * gx[i][3] + gr[i][3];
const bool held = (p[k] <= ctx_.b_floor && g > 0) || (p[k] >= ctx_.b_ceiling && g < 0);
gradient[k] = held ? 0.0 : g;
}
}
return std::isfinite(*cost);