|
| 1 | +# Quantum-chemistry primitives |
| 2 | + |
| 3 | +Domain-specific fused kernels where the whole computation — contraction, elementwise shaping, reduction — lives in a single NKI program. The architectural core of trntensor (see [Architecture](../architecture.md)). |
| 4 | + |
| 5 | +## `trntensor.mp2_energy(B, eps_occ, eps_vir) -> scalar` |
| 6 | + |
| 7 | +Density-fitted second-order Møller–Plesset correlation energy. |
| 8 | + |
| 9 | +``` |
| 10 | +E_MP2 = Σ_{i,j,a,b} T_{i,j,a,b} (2 T_{i,j,a,b} - T_{i,j,b,a}) / Δ_{i,j,a,b} |
| 11 | +
|
| 12 | +T_{i,j,a,b} = Σ_P B[i, a, P] B[j, b, P] |
| 13 | +Δ_{i,j,a,b} = ε_i + ε_j - ε_a - ε_b |
| 14 | +``` |
| 15 | + |
| 16 | +### Arguments |
| 17 | + |
| 18 | +- `B: (nocc, nvir, naux) tensor` — density-fitted ERI coefficients |
| 19 | +- `eps_occ: (nocc,) tensor` — occupied orbital energies |
| 20 | +- `eps_vir: (nvir,) tensor` — virtual orbital energies |
| 21 | + |
| 22 | +### Returns |
| 23 | + |
| 24 | +A 0-D tensor containing the correlation energy. |
| 25 | + |
| 26 | +### Example |
| 27 | + |
| 28 | +```python |
| 29 | +import torch |
| 30 | +import trntensor |
| 31 | + |
| 32 | +nocc, nvir, naux = 5, 19, 72 |
| 33 | +B = torch.randn(nocc, nvir, naux) * 0.1 |
| 34 | +eps_occ = -torch.sort(torch.rand(nocc))[0] - 0.5 |
| 35 | +eps_vir = torch.sort(torch.rand(nvir))[0] + 0.1 |
| 36 | + |
| 37 | +E = trntensor.mp2_energy(B, eps_occ, eps_vir) |
| 38 | +print(f"E_MP2 = {E.item():.6f}") |
| 39 | +``` |
| 40 | + |
| 41 | +### Backend behaviour |
| 42 | + |
| 43 | +- **CPU**: falls back to a Python loop over `(i, j)` pairs composing `torch.einsum` |
| 44 | + and element-wise ops. Same as `examples/df_mp2_einsum.py`. |
| 45 | +- **Trainium (NKI)**: dispatches a single `@nki.jit` program that |
| 46 | + - accumulates `T` in PSUM via `nisa.nc_matmul`, |
| 47 | + - builds `Δ` on the Vector Engine from SBUF-resident `ε` tiles, |
| 48 | + - folds the energy into a scalar accumulator in SBUF, |
| 49 | + - writes one partial per `(i, j)` pair to HBM. |
| 50 | + |
| 51 | +The host sums the `(nocc, nocc)` partial matrix into the final scalar. No intermediate four-index `T` tensor is ever materialized. |
| 52 | + |
| 53 | +### Current limitations |
| 54 | + |
| 55 | +- Single-tile path only: `nvir ≤ 128` and `naux ≤ 128`. Larger systems raise `NotImplementedError` — K/M tiling is a follow-up. |
| 56 | +- Dispatch overhead still dominates at small sizes; see [Benchmarks](../benchmarks.md) for the honest comparison against the Python loop. |
0 commit comments