Conversation
The edge head can now emit a per-atom latent polarizability alongside the
charge and bond dipole (Allegro-LES's construction from the polarizable
multipole LES paper, arXiv 2605.05746), feeding upstream les's
non-self-consistent induced-dipole energy -1/2 E_i.alpha_i.E_i.
les_alpha='iso' one scalar a_e per edge, scatter-summed -> alpha_i
les_alpha='aniso' two scalars per edge, a_e.I + b_e.(r r^T - I/3):
isotropic + traceless bond-axial parts, symmetric and
equivariant by construction (a lone bond is uniaxial)
l0 is packed [q | u | alpha] (1 or 9 extra columns); ecenet.les.unpack_l0
is the one place that knows the layout and model.les_flags carries the
flag. Alpha slots are zero-init (not a saddle: E_lr is linear in alpha),
les_charge_scale leaves alpha alone.
ecenet/les.py: the periodic path passes latent_alphas through to upstream;
the vectorized isolated path forms the field of the fixed multipoles from
the masked f_qu/f_uu kernels and adds the induced term (verified equal to
upstream's loop in energies and gradients, and against finite differences).
New born_charges() is the single induced-aware Z* implementation behind the
calculator and eval_spice_bec; total_polarizability() sums alpha_i per
structure (paper Eq. 29 -- exactly dP/dE_ext for this model, verified).
Calculator: results['les_alphas'] stashed on every force call;
compute_polarizability(atoms) returns the (3,3) latent tensor (physical for
isolated molecules; bulk needs the eps_e unscaling of the paper's Eqs. 23-24).
Trainers, predict_charges, eval_spice_bec take/handle the flag; README notes.
Tests: model-side layout/equivariance/uniaxial-bond/scale; wrapper parity
with upstream (iso/aniso x dipoles on/off), FD forces, periodic path,
born_charges; end-to-end xyz-trained 'aniso' checkpoint through
load_calculator (joint-graph forces, stress FD, sum(alpha) == dP/dE_ext,
BEC with induced dipoles); rMD17 trainer smoke with 'iso'.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019oREKbosSjju8EEuuPhHea
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
Adds an optional latent polarizability head to the LES edge read-out, feeding upstream
les's non-self-consistent induced-dipole term. This is the Allegro-LES construction from the polarizable-multipole LES paper (Kim, King, Park et al. 2026, arXiv 2605.05746), transplanted onto ECENet's edge frames.les_alpha='iso': one scalar per edge, scatter-summed to a per-atom α_i.les_alpha='aniso': two scalars per edge,a_e·I + b_e·(r̂r̂ᵀ − I/3)— an isotropic part plus a traceless bond-axial part. Symmetric and equivariant by construction; a lone bond gives the uniaxial α_∥/α_⊥ of a diatomic.l0 = [q | u | α];ecenet.les.unpack_l0is the one place that knows the layout,model.les_flagscarries the flag. α slots are zero-init (not a saddle:E_lris linear in α);les_charge_scaledoesn't touch α.Energy. The periodic path passes
latent_alphasstraight to upstream's Ewald. The vectorized isolated path forms the field of the fixed multipoles from the already-built maskedf_qu/f_uukernels and adds−½ E_i·α_i·E_i.Read-outs.
LESLongRange.born_charges()is now the single Z* implementation behind the calculator andeval_spice_bec, going through upstream's forward when α is present so the induced dipoles are part of the polarization.total_polarizability()sums α_i per structure (paper Eq. 29 — exactly dP/dE_ext for this model). The calculator stashesresults['les_alphas']and gainscompute_polarizability(atoms). All four trainers andpredict_chargestake/handle the flag.Test plan
tests/test_les.py: packed layout, α = 0 at init, 'iso' invariant / 'aniso'RαRᵀ-equivariant and symmetric, lone bond uniaxial with r̂ as principal axis,les_charge_scaleleaves α alone, batched variants consistent, bad configs rejectedtests/test_les.py: vectorized isolated path == upstream loop for iso/aniso × dipoles on/off (energies and gradients, worst 2e-15), FD forces 5e-11, periodic path exact, α = 0 reduces to the no-α energy,born_chargesα = 0 == direct BEC calltests/test_xyz_trainer.py: xyz-trained 'aniso' checkpoint throughload_calculator— joint-graph forces, stress FD 2e-13 through the periodic α path, α stashed,compute_polarizability== Σα_i == dP/dE_ext via upstreame_ext(autograd), BEC finite with a non-zero induced part, α-less checkpoint refusedtests/test_trainer_les.py: rMD17 smoke withles_alpha='iso'ruffcleanNotes
🤖 Generated with Claude Code
https://claude.ai/code/session_019oREKbosSjju8EEuuPhHea