Metadata-Version: 2.4
Name: c2-invariants
Version: 0.1.1
Summary: Real-space topological invariants for C2-symmetric 2D crystals
Requires-Python: >=3.12
Requires-Dist: numpy>=1.24
Requires-Dist: scipy>=1.10
Description-Content-Type: text/markdown

# c2-invariants

Real-space topological invariants for C2-symmetric 2D crystals.

> **Start here:** the full derivation of what this package computes — from
> the spinless real-space invariant of van Miert and Ortix (2018) through the
> Kooi, van Miert and Ortix (2021) partial-Chern plus $\mathbb Z_2$-winding
> construction for spinful + TRS systems — is in
> [docs/real-space-invariants.md](docs/real-space-invariants.md). The other
> method docs cover the algorithmic details.

## Installation

```bash
pip install c2-invariants
```

Or with [uv](https://docs.astral.sh/uv/):

```bash
uv add c2-invariants
```

For development (editable install), run this **from inside** the package
directory (the folder that contains `pyproject.toml`):

```bash
uv pip install -e .
```

If you keep this repo nested inside a larger project, `cd` into this
folder first, then use the same command.

## Quick start

```python
import numpy as np
from c2_invariants import C2Model, make_invariant

# Define H(kx, ky) -> ndarray, Hermitian and 2π-periodic in kx and ky
def my_hamiltonian(kx, ky):
    ...  # return (N, N)

c2_op = ...  # (N, N) k-independent C2 matrix (same gauge as H)

model = C2Model(
    h_func=my_hamiltonian,
    n_occ=1,
    c2_op=c2_op,
)

inv = make_invariant(model)
print(inv.nu("1d"))      # real-space invariant at Wyckoff 1d
print(inv.c2_counts)     # C2 eigenvalue counts at HSPs (cached property)
```

## Documentation

| Topic | Markdown |
|-------|----------|
| **Concepts and derivation (start here)** — Wannier counting, spinless and spinful regimes, and the partial-Chern plus $\mathbb Z_2$-winding construction for spinful + TRS | [docs/real-space-invariants.md](docs/real-space-invariants.md) |
| Boundary gauge on the EBZ loop (includes sector-I Berry phase and boundary partial Chern $C_I^{\rm bnd}$, §7) | [docs/boundary-gauge.md](docs/boundary-gauge.md) |
| Interior gauge on the half BZ | [docs/interior-gauge.md](docs/interior-gauge.md) |
| $\mathbb Z_2$ winding (boundary vs interior) | [docs/winding-number.md](docs/winding-number.md) |

For the TRS regime (`trs=True`), the library builds a $C_2 \cdot \Theta$-symmetric
Kramers gauge internally; the documentation above covers both the theory and
each stage of that pipeline.

## Conventions

The formulas use the four time-reversal invariant momenta
Γ = (0, 0), X = (π, 0), Y = (0, π), M = (π, π). That matches a **square**
reciprocal-lattice embedding where `H(kx, ky)` is **2π-periodic in both**
`kx` and `ky`. If your model is written in other coordinates, map it to
this convention before calling the library.

The symmetry must be given as a **single** `c2_op` matrix: a **k-independent**
C2 operator in the same Bloch gauge as `H` (no extra momentum-dependent
factors in `c2_op`).

**Time reversal (spinful + `trs=True`).** You must pass `trs_unitary`: the
unitary `U` in `Θ = U K` (complex conjugation `K`), in the **same** basis as
`H` and `c2_op`. The helper `standard_trs_unitary_spin_pairs(n_bands)` builds
block `i σ_y` on each consecutive index pair `(0,1), (2,3), …`. That assumes
**spin grouped inside each two-dimensional orbital block**, with blocks in
increasing index order. For a spinful honeycomb two-atom cell, a common match
is **A↑, A↓, B↑, B↓** (indices 0–1 = sublattice A, 2–3 = B). If your basis
orders degrees of freedom differently (e.g. spin interleaved across
sublattices), supply a custom `trs_unitary` (or permute `H` and `c2_op` into
this block structure first).

## Three regimes

| Regime | `spinful` | `trs` | Class | Invariant | Reference |
|---|---|---|---|---|---|
| Spinless | `False` | `False` | `SpinlessInvariant` | nu from Hadamard inversion of C2 counts | van Miert & Ortix, *Phys. Rev. B* **98**, 235130 (2018) |
| Spinful, no TRS | `True` | `False` | `SpinfulInvariant` | nu with Chern correction | van Miert & Ortix (2018) |
| Spinful + TRS | `True` | `True` | `TRSInvariant` | Partial nu^I via Kramers sector decomposition | Kooi, van Miert & Ortix, *npj Quantum Materials* **6**, 1 (2021) |

With **`trs=True`**, set **`trs_unitary`** on `C2Model`; see **Conventions**
above for `Θ = U K` and the basis assumed by
`standard_trs_unitary_spin_pairs`.

## Method and references

The constructions implemented here are introduced in two papers:

- G. van Miert and C. Ortix, *Phys. Rev. B* **98**, 235130 (2018).
- S. Kooi, G. van Miert, and C. Ortix, *npj Quantum Materials* **6**, 1 (2021).

The **spinless real-space invariant** (Hadamard inversion of $C_2$ eigenvalue
counts at the four TRIMs) is the construction of van Miert and Ortix (2018);
the spinful, no-TRS regime extends it with a Chern correction.

The **spinful + TRS** regime implements the partial Chern number $C_I^{\rm bnd}$,
the $\mathbb Z_2$ winding $\nu_{Z2}$, the SO($N$) branch-cut indicator
(Eqs. (14)-(15) of Kooi et al.), and the $C_2 \Theta$-symmetric parallel-transport
gauge of Kooi, van Miert and Ortix (2021).

The package's parallel transport runs on a $P = C_2 \Theta$-invariant *real*
frame, with the Kramers-paired sectors recovered at the end by a single fixed
unitary change of basis $W$. This is mathematically equivalent to the
complex-Kramers-basis SVD parallel transport of Supplementary Note VIII of
Kooi et al.

## Citing

If you use this package in academic work, please cite both method papers above.

## Dependencies

Only `numpy` and `scipy`. No tight-binding framework required — Hamiltonians
are plain callables `(kx, ky) -> ndarray`; see the **Conventions** section
earlier in this file.
