Skip to content

Express analytical bridging as an explicit linear_ener composition instead of a bridging_method flag #5948

Closed

Description

@wanghan-iapcm

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, ...})  # -> LinearEnergyModel

Why 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

  1. Type confusion — a standard (or dpa4) request silently returns a LinearEnergyModel.
  2. Implicit coupling — the radii are pushed into the sibling descriptor's InnerClamp/BridgingSwitch behind the user's back.
  3. 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_types to model-level pair_exclude_types and 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:

  1. Register inner_potential as a model type so it can be named as a linear_ener child.
  2. Have the composition derive the sibling descriptor's InnerClamp/BridgingSwitch from the inner_potential child 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.
  3. With the composition explicit, pair_exclude_types belongs 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.
  4. Keep bridging_method as sugar that expands to the canonical form through ONE normalizer (not per-builder), or deprecate it once the examples are migrated.
  5. Land pt and pt_expt together; argcheck is shared, so a schema that accepts a spelling one backend ignores is the same silent-divergence bug in a new place.

Related

Activity

  1. added a commit that references this issue on Aug 15, 2026
    ed691aa
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions