feat(state): make pbc a per-system attribute - #594
Conversation
During __init__ the dataclass assigned pbc before system_idx, so the (3,) to (n_systems, 3) broadcast in __setattr__ could not run at construction time and had to be duplicated in __post_init__. Declaring pbc after system_idx makes n_systems available when pbc is assigned, leaving a single broadcast site in __setattr__ and only shape validation in __post_init__. kw_only=True keeps the public API unchanged.
|
is this ready to merge? |
|
Yes, ready for review. One thing I'd like your eyes on: some potentials don't support mixed pbc, so they won't benefit from this change until upstream adds support. To keep them working, |
Yeah this is likely a reason to hold off merging this for the time being. I hope to have some more time to review soon but have been busy with an international move. |
|
No rush at all, and good luck with the move! I think the concern is reasonable, but the invariant break is confined to the wrapped forward calls and is meant to be temporary until the upstream integrations accept per-system pbc. I checked that this fix should be straightforward: the necessary change is only a 2-3 line shape check. Overall I think the benefits outweigh this temporary cost. Besides improving batching efficiency for mixed datasets, storing pbc per system makes it behave like cell everywhere: slicing, splitting, popping, and concatenation handle it consistently. In particular, |
Summary
SimState.pbca per-system attribute of shape(n_systems, 3); a bool,list[bool], or(3,)tensor is broadcast to all systems. Moving it from_global_attributesto_system_attributeslets slicing, splitting, popping, and concatenation handle it likecell.atoms_to_state/structures_to_stateaccept inputs with different pbc instead of raising, andstate_to_atoms/state_to_structures/ trajectory files store each system's own pbc row.require_full_pbc; elastic tensor calculation now rejects systems that are not fully periodic.(3,)row on a shallow copy (_to_legacy_pbc_state) before delegating, because those integrations broadcaststate.pbcthemselves assuming the old shape; mixed-pbc batches raise a clear error there.pbcaftersystem_idxso__setattr__can broadcast a(3,)row already during__init__, leaving a single broadcast site (__post_init__only validates the shape). Simplify pbc handling inautobatchingandionow that pbc is always a tensor.Related issue: #584
Compatibility
Breaking:
get_attrs_for_scope:pbcmoved from"global"to"per-system".Unchanged:
list[bool]/(3,)inputs are still accepted and broadcast to all systems.(3,)pbc array; existing files stay readable.Discussion points
_to_legacy_pbc_statehands third-party forward() a SimState whose pbc temporarily violates the(n_systems, 3)invariant. The preferred fix is upstream support for per-system pbc in the integrations; until then the shim keeps the current orb / NequIP / metatomic / fairchem releases working unchanged, since they only read plain attributes off the state.state.pbc = <1-D value>after construction broadcasts any length without validation (__post_init__runs only at construction). Missing validation is pre-existing, but should__setattr__enforce a length-3 row?Checklist
Before a pull request can be merged, the following items must be checked: