Configuration and Tuning
Overview
All gauNEGF default parameters live in gauNEGF.config. You can override them locally
by passing them as arguments to contact setup functions (eta=, T=) or to SCF (conv=, damping=).
This guide covers the parameters most likely to need tuning when optimizing convergence for your
system.
Note
Module-level constants (SCF_DAMPING, ETA, SURFACE_GREEN_CONVERGENCE,
etc.) are bound into gauNEGF.scf/scfE/density at import time
(from gauNEGF.config import ...) and as function default-argument
values. Setting config.X = ... after those modules are already
imported has NO effect (this includes config.CLEAR_JAX_CACHES_PER_CYCLE
and config.USE_INERTIA_EMIN). config.HOST_BLAS_THREADS is the
exception: it is read each time the density step runs.
To change a default globally, set config.X = ... before importing
gauNEGF.scf/scfE/density for the first time – otherwise pass
the value per-call (conv=, damping=, eta=, T=, tol=,
maxcycles=), which always works regardless of import order.
Default Configuration
The table below lists the configuration constants that control convergence behavior. You need not change most of them; the defaults are conservative and appropriate for most DFT + NEGF calculations.
Parameter |
Default |
Type |
Purpose |
|---|---|---|---|
|
0.02 |
float |
Controls density matrix update aggressiveness in SCF |
|
1e-3 |
float |
SCF convergence threshold (eV or a.u.) |
|
100 |
int |
Maximum number of SCF iterations before stopping |
|
1e-5 |
float (eV) |
Imaginary broadening for Green’s function |
|
0.0 |
float (K) |
Temperature for Fermi-Dirac distribution in contacts |
|
1e-3 |
float |
Tolerance for Fermi energy search |
|
10 |
int |
Maximum search cycles before returning Fermi energy |
|
1e-5 |
float |
Green’s function convergence tolerance for iterative inversion |
|
1e-4 |
float |
Tolerance for adaptive energy integration |
|
4 |
int |
Number of previous densities in Pulay mixing history |
|
True |
bool |
Lower integration bound from |
|
None |
int or None |
Host BLAS threads inside |
|
False |
bool |
Purge the compiled-kernel cache and JAX caches every SCF cycle |
Lower Integration Bound (USE_INERTIA_EMIN)
With USE_INERTIA_EMIN = True (default), each NEGFE.FockToP cycle
calls gauNEGF.density.find_lower_bound(). It starts EMIN_BUFFER
below the lowest device eigenvalue and steps down until the inertia count
(number of negative eigenvalues) of the Hermitian part of
E*S - F - Sigma(E) equals its value at ENERGY_MIN, i.e. until every
pole lies above, then moves a further EMIN_BUFFER down. A single complex
contour is integrated from that floor to the Fermi energy.
Set USE_INERTIA_EMIN = False before importing gauNEGF.scfE to use
the two-contour path always. A fixed grid set with
setIntegralLimits(N1=..., N2=..., Emin=...) bypasses both.
Host BLAS Threads (HOST_BLAS_THREADS)
FockToP runs inside gauNEGF.utils.blas_limit(), which caps the
host NumPy/SciPy BLAS thread pools with threadpoolctl for the duration
of the density step and restores them afterwards. The default cap is
min(16, ncpu // 4) (at least 1), where ncpu is the number of cores
the process may run on (its CPU affinity, not the node total). Set
config.HOST_BLAS_THREADS to an integer to override the cap. If
threadpoolctl is not installed, gauNEGF warns once and runs uncapped.
gauNEGF no longer sets XLA_FLAGS; JAX sizes its own thread pool.
Kernel Cache (CLEAR_JAX_CACHES_PER_CYCLE)
The integrators compile their JAX kernels once per contact object and
reuse them across SCF cycles; contact Fermi shifts enter as traced
arguments, so a Fermi update does not trigger a recompile.
CLEAR_JAX_CACHES_PER_CYCLE = True drops that cache
(gauNEGF.integrate.clear_kernel_cache()) and calls
jax.clear_caches() after every SCF cycle. Leave it off unless memory
use grows from cycle to cycle; turning it on forces a recompile every
cycle.
Fermi Search Method (fermiMethod)
The fermiMethod parameter controls the root-finding algorithm used to determine
the Fermi energy during the SCF. This is passed to
gauNEGF.scfE.NEGFE.setVoltage() to select how gauNEGF solves for the
electron count. Which electrons are counted is set separately by the
fermiCount argument of the contact setup call (setContact1D default
'contact', setContactBethe default 'device_bare'); see
1D Chain Contacts in gauNEGF and Bethe Lattice Contacts. When the previous cycle’s
electron-count error is already below the tolerance, the search is skipped
for that cycle (the log prints Fermi frozen) and re-engages when the
count moves.
Warning
For 1D contacts set up with atom indices only (no explicit tau/alpha/beta matrices), DO NOT specify a fermi energy in setVoltage or the electron count will become unphysical! Instead use defaults or set fermiMethod . Example: negf.setVoltage(0.0)
Method |
Stability |
Speed |
When to use |
|---|---|---|---|
|
Highest |
Slow |
Always safe; default fallback when others fail. Guaranteed convergence but requires many iterations. |
|
High |
Medium |
Good general-purpose default. Overshoot unlikely, defaults to bisection upon failure. |
|
Medium |
Medium-Fast |
Slightly faster than muller; muller remains the safer default. Balances stability and speed with 3rd order polynomial fitting. |
|
Low |
Fast |
Best for highly coupled contacts, unstable for weak contacts. Defaults to bisection upon failure |
|
Lowest |
Very fast |
Stable only for weakly coupled contacts, uses previous guess upon failure (check warnings). Also rescales the density matrix every cycle to force the target electron count ( |
This stability/speed ranking applies uniformly across contact types (1D,
Bethe, constant sigma): 'muller' is the safe default everywhere;
'poly' trades a little stability for speed and is a reasonable choice
when you have already validated a system converges cleanly.
See Choosing a Contact Type for guidance on which contact type is appropriate, and 1D Chain Contacts in gauNEGF for detailed setup instructions.
SCF_DAMPING
The SCF_DAMPING parameter controls how aggressively the density matrix is updated
each SCF iteration. It acts as a mixing coefficient: new density = (1 - damping) * old + damping * computed.
Default: 0.02
Tuning guidelines:
Recommended Range: 0.02 to 0.05 – the default range for production runs. Wider excursions (down toward 0.005 or up to 0.1) are reasonable when diagnosing a specific problem (see the two-phase strategy below, or the SCF tuning workflow’s Steps 2-3), but 0.02-0.05 is the range to start from and return to.
High Mixing (up to 0.1) for saddle points Use if iterations seem “stuck”, try with or without pulay interpolation.
Low Mixing (down toward 0.005) for unstable systems Use when SCF oscillates or overshoots, increase nPulay if unstable.
Production strategy:
For difficult systems, use a two-phase approach: run SCF with low mixing first to find the convergence basin, then switch to higher mixing to escape any saddle points.
# Phase 1: Can be unstable until contacts mixed into system
negf.updatePulay(10)
negf.SCF(conv=1e-3, damping=0.002, maxcycles=100)
# Phase 2: Ensure not in a saddle point
negf.updatePulay(4)
negf.SCF(conv=1e-3, damping=0.1, maxcycles=100)
ETA (Broadening Parameter)
The ETA parameter controls the imaginary part of the energy (eta: E -> E + i*eta)
added to the Green’s function. This broadening stabilizes the inversion and smooths
spectral features.
Default: 1e-5 eV
Typical overrides:
1e-3 eV: Higher eta values can improve stability of 1D contacts especially at band edges
1e-5 eV (default): Recommended for most production transport calculations. Provides sharp spectral resolution while maintaining good conditioning.
1e-6 eV: Use for precise calculations to capture band edges exactly, may cause numerical issues if the Green’s function is poorly conditioned.
Trade-off: Higher ETA speeds convergence and broadens spectral features; lower ETA gives sharper spectra but requires better conditioning. For production transport calculations, use the default (1e-5) unless specifically tuning spectral resolution.
Pass locally:
# Set ETA for 1D contact
negf.setContact1D([[1,2,3],[4,5,6]], eta=1e-3)
# Set ETA for Bethe contact
negf.setContactBethe([[1,2,3],[4,5,6]], eta=1e-5)
TEMPERATURE
The TEMPERATURE parameter controls thermal broadening in the contacts. It does not directly
affect the device Hamiltonian, only the Fermi-Dirac distribution in the contact self-energy.
Default: 0.0 K (zero temperature, sharp Fermi cutoff)
Common values:
0.0 K (default): Zero-temperature transport. Sharp electron/hole cutoff at the Fermi energy. Appropriate for single-point transmission calculations and most DFT+NEGF workflows.
300 K: Room temperature. Adds thermal broadening (kT ~ 0.026 eV); electrons and holes leak slightly across the Fermi energy. Use for finite-temperature transport or to model thermal effects.
Note
The finite-temperature equilibrium contour was corrected in this
release (see CHANGELOG.md); T > 0 results computed with earlier
versions should be recomputed. As a side benefit, finite T moves the contour’s
real-axis touchdown away from the Fermi energy, which can improve
integration robustness for metallic systems with frontier states
at E_F.
Pass locally:
# Set temperature for 1D contact
negf.setContact1D([[1,2,3],[4,5,6]], T=300)
# Set temperature for Bethe contact
negf.setContactBethe([[1,2,3],[4,5,6]], T=300)
Fermi Energy Search Tolerances
Two tolerances control Fermi energy accuracy:
- FERMI_CALCULATION_TOL (default 1e-3):
Tolerance on the electron count during the Fermi search, as an absolute electron count (per spin for
spin='r'; total for'u'/'ro'/'g'). Inside the SCF the search converges when|N_computed - N_target| < min(FERMI_CALCULATION_TOL, convLevel), whereconvLevelis the current SCF convergence level. Loosen to 1e-2 if Fermi search oscillates; tighten to 1e-4 for strict charge neutrality.- FERMI_SEARCH_CYCLES (default 10):
Maximum number of root-finding iterations before returning. If the solver does not converge within this limit, gauNEGF returns the best estimate and logs a warning. Increase to 20-30 for difficult systems; decrease to 5 if Fermi search is a bottleneck.
Surface Green’s Function Convergence
- SURFACE_GREEN_CONVERGENCE (default 1e-5):
Convergence threshold for the iterative inversion that builds the contact surface Green’s function. The default is the lowest safe value: going below 1e-5 can produce numerical instability, because the recursion simply stops at its internal iteration cap (
MAX_ITER=10000) before reaching the tighter tolerance, leaving an unconverged surface Green’s function baked into the contour integration – this is not recommended. Going above 1e-5 (e.g. 1e-4) speeds up contact setup at the cost of slightly less accurate self-energies, which is useful for exploratory runs or initial convergence sweeps.
Integration Tolerances
- ADAPTIVE_INTEGRATION_TOL (default 1e-4):
Tolerance for adaptive energy integration in density matrix calculations. Set as a threshold for the maximum error (element-wise) in the density matrix. NOTE: should be below SCF convergence criteria
Integration Methods: Complex Contour vs Real-Axis
For hands-on comparison of gauNEGF integration approaches, see
Integration Demo (docs/source/examples/IntegralDemo.ipynb) –
a step-by-step notebook that illustrates the trade-offs between complex
contour integration and real-axis energy integration.
Workflow: Tuning Convergence
- Step 1: Start with defaults.
Most systems converge with factory settings. Run SCF and check the convergence history.
- Step 2: If SCF oscillates or diverges:
Tighten mixing to lower value:
negf.SCF(conv=1e-3, damping=0.005)Adjust Pulay mixing value if unstable:
negf.updatePulay(9)Check that contacts are physically reasonable (see Choosing a Contact Type)
- Step 3: If SCF is very slow:
Use two-phase approach: higher mixing (0.1) then lower (0.01)
Increase ETA in initial runs:
negf.setContact1D([[1,2],[5,6]], eta=1e-3)Use closed shell spin for initial runs, then add spin degrees of freedom later
- Step 4: If Fermi search fails or gives non-physical electrons:
Turn on fermi search in initial runs - fermi energy setpoint may be near orbital energies
Explicitly set fermiMethod in setVoltage:
negf.setVoltage(0.0, fermiMethod='muller')Add a finite temperature to smooth out integration:
negf.setContact1D([[1,2],[5,6]], T=300)Otherwise revert back to bisection (
fermiMethod='bisect') if all else fails
See Also
Choosing a Contact Type – Choosing between 1D and Bethe lattice contacts
1D Chain Contacts in gauNEGF – 1D contact setup and atom indexing
Guide 5: Workflow Recipes – Production workflows and best practices
gauNEGF.config– Source of all default constants