feynlag.pheno.lorentz.contract_to_dots

feynlag.pheno.lorentz.contract_to_dots(expr, dot)[source]

Reduce a fully contracted tensor expression to a plain scalar.

TensExpr.replace_with_arrays raises ValueError: p1(L_0) not found on contracted dummy indices (SymPy 1.14), so the structure is walked directly: for each TensMul, every slot of every component is paired with its index, dummy indices are matched up, and each matched pair of momentum heads becomes dot(head_a, head_b).

Any surviving metric component is rejected rather than guessed at: the caller must run .contract_metric(LorentzIndex.metric) first (a naive per-pair rule would turn g^{ab}g_{ab} = 4 into 16).

Note

This is the one function touching semi-private SymPy tensor API (TensMul.components/.get_indices()/.coeff). It is isolated here on purpose and pinned by unit tests, so a future SymPy change breaks exactly one place, loudly.

Parameters:
  • expr – tensor expression with no free indices.

  • dot – callable (head_a, head_b) -> scalar giving p_a·p_b.

Raises:

ValueError – an index is left uncontracted (a bug upstream).