Summary
In both the develop branch and the LTS branch, the Kerker preconditioner is silently bypassed whenever mixing_beta <= 0.1. This means the mixing_gg0 parameter — whether explicitly set by the user or left at its default value of 1.0 — has no effect at all in this regime. The value is not overwritten, but the only code that consumes it is short-circuited, which is functionally equivalent to forcing mixing_gg0 = 0.
This is problematic because small mixing_beta values (≤ 0.1) are precisely the recommended remedy for hard-to-converge (e.g. metallic) systems, and the documentation explicitly suggests combining them with Kerker screening — which then silently does nothing.
Details
Affected code
develop branch — source/source_estate/module_charge/charge_mixing_preconditioner.cpp:
// Kerker_screen_recip(), line 10
if (this->mixing_gg0 <= 0.0 || this->mixing_beta <= 0.1)
{
return;
}
// Kerker_screen_real(), line 81
if (this->mixing_gg0 <= 0.0001 || this->mixing_beta <= 0.1)
{
return;
}
Analogous guards exist for the magnetization channel (mixing_beta_mag <= 0.1, lines 37 and 117).
LTS branch — identical logic in source/module_elecstate/module_charge/charge_mixing_preconditioner.cpp, lines 9 (Kerker_screen_recip) and 64 (Kerker_screen_real).
Origin
The condition was introduced in commit 4865b77c8 — "Feature: improved implementation of kerker preconditioner (#3133)" — which changed the guard from if (this->mixing_gg0 <= 0.0) to if (this->mixing_gg0 <= 0.0 || this->mixing_beta <= 0.1). The same PR changed the filter lower bound from a hardcoded 0.1 to 0.1 / mixing_beta (the predecessor of the current mixing_gg0_min / mixing_beta). When mixing_beta <= 0.1, that bound becomes ≥ 1, so filter_g = max(gg/(gg+gg0), gg0_min/beta) would degenerate into an amplification factor, and the authors chose to disable Kerker entirely in that regime.
Problems with the current behavior
-
Silent no-op with no warning. mixing_gg0 is printed to running.log in set_mixing() before the screening step, so the log still shows e.g. mixing_gg0: 1, giving the false impression that Kerker screening is active. Nothing in the output tells the user it has been turned off. (On develop, only the INPUT parameter help text mentions it: "Kerker preconditioner will be automatically turned off if mixing_beta <= 0.1." — the LTS documentation does not mention it at all.)
-
Documentation contradicts the behavior. The mixing_beta description on develop (read_input_item_elec_stru.cpp) recommends:
"For low-dimensional large systems, the setup of mixing_beta=0.1, mixing_ndim=20, and mixing_gg0=1.0 usually works well."
Since the guard uses <=, mixing_beta = 0.1 falls exactly into the disabled regime, so the recommended mixing_gg0 = 1.0 has no effect whatsoever.
-
Physically counterproductive. Small mixing parameters are most often needed for metallic or otherwise hard-to-converge systems, which are exactly the systems that benefit most from Kerker screening of charge sloshing. Users who try to combine mixing_beta < 0.1 with Kerker screening currently cannot do so — there is no way to override this behavior short of modifying the source.
Suggested improvements
Possible directions (not mutually exclusive):
- Decouple the two parameters: instead of disabling Kerker when
mixing_beta <= 0.1, clamp the filter lower bound (e.g. min(gg0_min / mixing_beta, 1.0)) so the preconditioner remains a valid suppression filter for small mixing_beta.
- At minimum, emit a clear runtime warning (in
running.log / stdout) whenever Kerker is auto-disabled, so the user is not misled by the printed mixing_gg0 value.
- Fix the documentation inconsistency: either change the recommended combination (
mixing_beta=0.1 + mixing_gg0=1.0) or change the guard to a strict < so the documented recipe actually works as written.
Environment / verification
Summary
In both the
developbranch and theLTSbranch, the Kerker preconditioner is silently bypassed whenevermixing_beta <= 0.1. This means themixing_gg0parameter — whether explicitly set by the user or left at its default value of1.0— has no effect at all in this regime. The value is not overwritten, but the only code that consumes it is short-circuited, which is functionally equivalent to forcingmixing_gg0 = 0.This is problematic because small
mixing_betavalues (≤ 0.1) are precisely the recommended remedy for hard-to-converge (e.g. metallic) systems, and the documentation explicitly suggests combining them with Kerker screening — which then silently does nothing.Details
Affected code
developbranch —source/source_estate/module_charge/charge_mixing_preconditioner.cpp:Analogous guards exist for the magnetization channel (
mixing_beta_mag <= 0.1, lines 37 and 117).LTSbranch — identical logic insource/module_elecstate/module_charge/charge_mixing_preconditioner.cpp, lines 9 (Kerker_screen_recip) and 64 (Kerker_screen_real).Origin
The condition was introduced in commit
4865b77c8— "Feature: improved implementation of kerker preconditioner (#3133)" — which changed the guard fromif (this->mixing_gg0 <= 0.0)toif (this->mixing_gg0 <= 0.0 || this->mixing_beta <= 0.1). The same PR changed the filter lower bound from a hardcoded0.1to0.1 / mixing_beta(the predecessor of the currentmixing_gg0_min / mixing_beta). Whenmixing_beta <= 0.1, that bound becomes ≥ 1, sofilter_g = max(gg/(gg+gg0), gg0_min/beta)would degenerate into an amplification factor, and the authors chose to disable Kerker entirely in that regime.Problems with the current behavior
Silent no-op with no warning.
mixing_gg0is printed torunning.loginset_mixing()before the screening step, so the log still shows e.g.mixing_gg0: 1, giving the false impression that Kerker screening is active. Nothing in the output tells the user it has been turned off. (Ondevelop, only the INPUT parameter help text mentions it: "Kerker preconditioner will be automatically turned off if mixing_beta <= 0.1." — theLTSdocumentation does not mention it at all.)Documentation contradicts the behavior. The
mixing_betadescription ondevelop(read_input_item_elec_stru.cpp) recommends:Since the guard uses
<=,mixing_beta = 0.1falls exactly into the disabled regime, so the recommendedmixing_gg0 = 1.0has no effect whatsoever.Physically counterproductive. Small mixing parameters are most often needed for metallic or otherwise hard-to-converge systems, which are exactly the systems that benefit most from Kerker screening of charge sloshing. Users who try to combine
mixing_beta < 0.1with Kerker screening currently cannot do so — there is no way to override this behavior short of modifying the source.Suggested improvements
Possible directions (not mutually exclusive):
mixing_beta <= 0.1, clamp the filter lower bound (e.g.min(gg0_min / mixing_beta, 1.0)) so the preconditioner remains a valid suppression filter for smallmixing_beta.running.log/ stdout) whenever Kerker is auto-disabled, so the user is not misled by the printedmixing_gg0value.mixing_beta=0.1+mixing_gg0=1.0) or change the guard to a strict<so the documented recipe actually works as written.Environment / verification
origin/develop(HEAD51f3c1cde) andorigin/LTSofdeepmodeling/abacus-develop.4865b77c8(PR Feature: improved implementation of kerker preconditioner #3133), which is an ancestor ofLTS.