Add a Newton chemical-potential search (mu_search='newton')#182
Open
k-yoshimi wants to merge 1 commit into
Open
Add a Newton chemical-potential search (mu_search='newton')#182k-yoshimi wants to merge 1 commit into
k-yoshimi wants to merge 1 commit into
Conversation
The chemical-potential adjustment re-evaluates the (expensive) lattice density
n(mu) at every step of the existing bracketing+Brent search. Because n(mu) is
smooth and monotonic and its derivative is available almost for free, a Newton
iteration usually needs fewer of those density evaluations.
- total_density_and_derivative(): returns (n, dn/dmu) in a single k-loop, where
dn/dmu = -(1/beta) sum_k w_k sum_block sum_iw Tr[G^2] (since dG/dmu = -G^2 and
the 0.5*n_orb tail term is mu-independent). Matsubara-only (guards iw_or_w).
- calc_mu_newton(): a Numerical-Recipes rtsafe safeguarded Newton. It brackets
the root (trying both directions), then takes a Newton step only when it stays
inside the bracket and reduces the residual fast enough, otherwise bisects. In
a charge gap (dn/dmu ~ 0) it therefore falls back to bisection, so it is never
less robust than bisection. It returns None (matching calc_mu) if it cannot
bracket or does not converge.
- New [system] mu_search option ('brent' default, or 'newton'); plumbed through
dmft_core to SumkDFTWorkerGloc. 'newton' adjusts mu from the Matsubara-summed
charge, so it requires no_tail_fit=True (enforced where the search runs).
Physics: the search is at fixed Sigma (the standard DMFT inner step), so dn/dmu
is exact and both methods solve the identical n(mu;Sigma)-N=0; Newton only
changes the path, not the root. Sigma's mu-dependence is captured by the outer
self-consistency.
Measured (square, n_orb=24, no_tail_fit=True): the Gloc evaluation went from
19.8 s (brent, 6 density evaluations) to 8.4 s (newton, 1 evaluation) with an
identical total charge, the gain being largest near self-consistency where mu
barely moves.
Tests: tests/non-mpi/mu_newton covers the root finder (smooth, charge-gap,
wrong-signed initial derivative, already-converged, non-convergence -> None),
the iw-only guard, parameter defaulting/validation, and the derivative against a
finite difference. Default mu_search='brent' leaves existing behavior unchanged.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Contributor
Author
Full-run validation: newton vs brent across all iterationsTo confirm
Both μ and Σ agree at every iteration to ~1e-7–1e-6, well below |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The chemical-potential adjustment re-evaluates the (expensive) lattice density
n(μ)at every step of the existing bracketing + Brent search (calc_mu). Sincen(μ)is smooth and monotonic and its derivative is almost free, a Newton iteration usually needs fewer of those density evaluations.total_density_and_derivative()— returns(n, dn/dμ)in a single k-loop (Matsubara-only; guardsiw_or_w).calc_mu_newton()— a Numerical-Recipesrtsafesafeguarded Newton: brackets the root (both directions), takes a Newton step only when it stays in the bracket and reduces the residual fast enough, else bisects. In a charge gap (dn/dμ ≈ 0) it falls back to bisection, so it is never less robust than bisection. ReturnsNone(likecalc_mu) on failure.[system] mu_searchoption ('brent'default, or'newton'), plumbed throughdmft_coretoSumkDFTWorkerGloc.'newton'adjusts μ from the Matsubara-summed charge, so it requiresno_tail_fit=True(enforced where the search actually runs).Why the analytic derivative is exact here
The μ-search is the standard DMFT inner step at fixed Σ, so
dn/dμhas no∂Σ/∂μterm and is exact. Both methods solve the identicaln(μ; Σ_fixed) − N = 0, so they find the same μ — Newton only changes the path. Σ's μ-dependence is captured by the outer self-consistency.Measured effect
Square model,
n_orb=24,no_tail_fit=True, one Gloc evaluation:The gain is largest near self-consistency, where μ barely moves between iterations (Newton's early return).
Tests
tests/non-mpi/mu_newtoncovers the root finder (smooth, charge-gap, wrong-signed initial derivative, already-converged, non-convergence→None), the iw-only guard, parameter defaulting/validation, and the derivative vs a finite difference. The defaultmu_search='brent'leaves existing behavior unchanged (wannier90 regression tests pass).🤖 Generated with Claude Code