The typed feature pipeline
Every E3GNN — the default MANDALA network, the DeepH,
DeepH-E3 and MACE-H presets and any custom model — is a
FeaturePipeline: an ordered list of stages that read
named feature slots and write new ones. Architecture names never select
code paths; they select YAML files.
Anatomy of a stage
pipeline:
inputs: # optional extra input contracts
message_batch: {domain: edge, representation: index, frame: none, support: message}
stages:
- id: radial # unique module name
transform: gaussian_basis
inputs: [edge_lengths] # positional, never inferred by name
outputs: [radial] # fresh slots; existing slots cannot be overwritten
options: {start: 0.0, stop: 6.0, n_gaussians: 32}
role: feature # feature | encoder | message | readout
initialization: {seed: 17, kind: component}
outputs: {hamiltonian: hamiltonian_native}
Slots are write-once. A stage cannot overwrite an input or a previously written slot, so residual links, parallel streams and long skip connections are explicit and the forward pass is a pure dataflow graph.
Inputs are positional. The meaning of each input is defined by its position in the transformation’s signature.
Outputs map operator names (
hamiltonian,overlap,density) to slots holding matrix-valued features on the output-edge support.Roles label stages.
role: readoutselects the trainable stages whenfreeze_backbone_train_heads_onlyfreezes everything else.Initialization can override a stage’s parameters with
normal,uniformorzeros(withstd,bound,gain) and isolate its random stream withseed;componentkeeps the layer’s own scheme.
Typed feature contracts
Every slot carries a FeatureSpec:
Field |
Values |
Meaning |
|---|---|---|
|
|
The kind of entity each row belongs to. |
|
|
How the numbers are to be interpreted. |
|
e3nn string, e.g. |
The exact irrep layout of irrep-valued features. |
|
|
Coordinate frame. Bond-frame components are not global irreps. |
|
|
The index set of edge-like entities. Two edge features with equal shapes but different supports are not interchangeable. |
|
permutation of |
Cartesian axis order of non-scalar irreps; global features use |
|
integer |
Width of non-irrep features. |
|
layout mapping |
How a custom relation is offset when graphs are batched. |
When the pipeline is compiled, every stage’s factory receives the specs of its inputs, validates them and returns the specs of its outputs. Mismatches — an edge feature where a node feature is expected, a vector where an invariant is required, two supports mixed in one sum, a readout whose irreps differ from the operator layout — raise an error at construction time.
Built-in input slots
The dataset and E3GNN.forward() provide these slots for every structure:
Slot |
Contract |
Content |
|---|---|---|
|
node, index |
Species index in the resolved |
|
node, |
One-hot species. |
|
edge, index |
Index of the ordered species pair \((a_i,a_j)\), one of \(N^2\). |
|
edge, |
One-hot species pair. |
|
relation, index |
Directed output edges \((i,j)\) and lattice shifts \(\bm L\). |
|
edge, geometry / scalar |
\(\bm r_{ij}^{\bm L}\) and \(\|\bm r_{ij}^{\bm L}\|\). |
|
node / graph, geometry |
Cartesian positions and lattice (rows), for differentiable geometry. |
|
index |
Graph membership in a batch. |
|
edge, index |
Mask of onsite edges. |
|
support |
A separately selected message graph (by default the output graph
without onsite edges) and its map onto output edges ( |
|
bond frame, bond neighbourhood |
Local bond frames and bond-neighbourhood relations for local-coordinate architectures. |
The flat MANDALA graph additionally uses edge_length_emb (Gaussian radial
basis), edge_sh (spherical harmonics), pred_pair_edges_static and
edge_partitions, which the model computes from the configuration.
Resolution: shapes from data
Recipes are resolved against the orbital vocabulary of the training data
before a model is built (net.configuration.resolve_configuration()).
Resolution fills in:
Variable |
Value |
|---|---|
|
Species list (alphabetical or by atomic number), \(N\), \(N^2\). |
|
Shell degrees of each species, e.g. |
|
Irreps of the packed edge vector covering every species pair. |
|
Codec description consumed by |
|
User-defined variables of the recipe. |
layout_rules compute further shapes, e.g. tensor_product_completion
finds the smallest intermediate irreps from which a tensor product can reach
the coupled layout. Resolution also freezes pipeline.operator_layout — the
exact species order, shell assignment and spin convention — into the
checkpoint; inference verifies it before reconstructing blocks.
Inspecting a pipeline
outputs, slots = model.pipeline(x, return_trace=True)
for sid, reads, writes in model.pipeline.bindings:
print(sid, reads, "->", writes, model.pipeline.feature_specs[writes[0]])
slots holds every intermediate tensor, which makes the trace a convenient
tool for equivariance debugging: rotate the input and compare slot by slot to
find the first stage that breaks the transformation law.
The registry
Transformations are registered by name:
from net.pipeline import FeatureSpec, register_transform
@register_transform("my_layer")
def build(options, inputs, mapper):
... # validate the FeatureSpecs in `inputs`
return module, [FeatureSpec(...)]
The factory receives the stage options (a dict), the list of input
specs and the shared BlockIrrepMapper, and
returns a torch.nn.Module together with one spec per output. At run time
the module is called with the input tensors in order; if it sets
accepts_physical_derivatives = True it also receives
physical_derivatives=.... Writing new layers and objectives develops this into a
complete workflow.
The compiler currently accepts 47 transformation names:
add, angular_degree_expansion, bond_frames, bond_harmonics, bond_local_linear, channel_linear, concat, cutoff_radial_expansion, embedding, endpoint_gather, endpoint_irrep_edge, endpoint_irrep_node, endpoint_message_aggregation, endpoint_scalar_edge, endpoint_tensor_product_edge, endpoint_tensor_product_node, gated_scalar_message, gaussian_basis, gaussian_envelope, graph_irrep_norm, indexed_aggregation, irrep_activation, irrep_cartesian_basis, irrep_linear, irrep_residual, irrep_to_bond, local_coordinate_message, local_orbital_output, neighbor_density, one_hot, pair_distance_affine, pair_radial_angular_embedding, partitioned_blocks_to_shells, partitioned_irrep_readout, periodic_displacement, projected_attention, radial_tensor_product, scalar_gated_node, scalar_linear, scale_features, shell_tensor_decode, species_irrep_affine, species_irrep_embedding, species_tensor_product, spherical_harmonics, symmetric_product, vector_lengths