Repository navigation
Express analytical bridging as an explicit linear_ener composition instead of a bridging_method flag #5948
Copy link
Copy link
Closed
Labels
Description
A bridged model is a linear composition — bridging_method builds a LinearEnergyModel whose atomic model is a LinearEnergyAtomicModel over [learned, InnerPotential]. But it is spelled as a flag on a non-composite model type, so the type you request is not the type you get:
get_standard_model({... "descriptor": {"type": "dpa4"}, ...}) # -> DPA4EnergyModel
get_standard_model({... "bridging_method": "ZBL", "bridging_r_inner": 0.8, ...}) # -> LinearEnergyModelWhy the flag exists
linear_ener is already the composition axis and takes exactly the right shape — a repeated models: list of full sub-model specs plus weights ("sum" supported). What is missing is the child: InnerPotential has no config-level model type. It exists only as InnerPotentialAtomicModel, so it cannot be named in models:. The flag is the workaround for that gap.
What the workaround costs
- Type confusion — a
standard(ordpa4) request silently returns aLinearEnergyModel. - Implicit coupling — the radii are pushed into the sibling descriptor's
InnerClamp/BridgingSwitchbehind the user's back. - Duplicated owners — every builder that accepts the flag must re-implement the composition, and they have already drifted: see Deprecate descriptor-scoped exclude_types in favour of the model-level build-seam owner #5947, where one builder promotes
descriptor.exclude_typesto model-levelpair_exclude_typesand the other does not, changing the energy of a 0.9 A Ni-O dimer by 79.97 eV (max force component 318.48 eV/A).
Proposed shape
"model": {
"type": "linear_ener", "weights": "sum", "type_map": ["Ni", "O"],
"pair_exclude_types": [[0, 1]],
"models": [
{"type": "standard", "descriptor": {"type": "dpa4", "...": "..."},
"fitting_net": {"type": "dpa4_ener", "...": "..."}},
{"type": "inner_potential", "mode": "ZBL", "r_inner": 0.8, "r_outer": 1.2}
]
}Tasks:
- Register
inner_potentialas a model type so it can be named as alinear_enerchild. - Have the composition derive the sibling descriptor's
InnerClamp/BridgingSwitchfrom theinner_potentialchild at build time. Bridging is not a pure sum — the switch must reach inside the learned child (it drives the SFPG gate, see DPA4/SeZM zone-bridging (SFPG) gate is incomplete under domain decomposition; blocks ZBL and spin+ZBL multi-rank #5906) — so this coupling has to be expressed somewhere; deriving it keeps a single source of truth instead of asking the user to write the radii twice and hoping they agree. - With the composition explicit,
pair_exclude_typesbelongs to the linear model and governs both children by construction. The promotion in Deprecate descriptor-scoped exclude_types in favour of the model-level build-seam owner #5947 then has nothing left to do and can be deleted rather than deprecated. - Keep
bridging_methodas sugar that expands to the canonical form through ONE normalizer (not per-builder), or deprecate it once the examples are migrated. - Land pt and pt_expt together;
argcheckis shared, so a schema that accepts a spelling one backend ignores is the same silent-divergence bug in a new place.
Related
- Deprecate descriptor-scoped exclude_types in favour of the model-level build-seam owner #5947 — the exclusion promotion; a symptom of task 3, independently shippable but subsumed by this.
- feat: SFPG cross-rank completion — capabilities, ZBL bridging and spin+ZBL multi-rank #5939 — surfaced this; that PR now rejects
bridging_methodundertype: "standard"in pt_expt rather than composing behind the type, so there is exactly one bridging owner per backend until this lands.
Activity
fix(pt_expt): bridging is a composition, so `standard` must reject it
refactor(model): express analytical bridging as an explicit linear_en…