Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
150 changes: 150 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
# SymmetricTightBinding.jl

## Overview

A Julia package for constructing symmetry-constrained tight-binding Hamiltonians in any
crystallographic space group (1D, 2D, 3D). Built on the framework of topological quantum
chemistry (TQC) and the theory of band representations.

Given a set of elementary band representations (EBRs) from Crystalline.jl and a list of
hopping ranges, the package:
1. Enumerates symmetry-related hopping orbits
2. Constructs the M-matrix encoding all allowed Hamiltonian terms
3. Enforces spatial symmetry, time-reversal, and hermiticity constraints via nullspace +
Zassenhaus intersection
4. Returns a `TightBindingModel` whose free parameters can be tuned to produce concrete
Hamiltonians

**Repository:** https://github.com/CrystallineOrg/SymmetricTightBinding.jl
**Depends on:** [Crystalline.jl](https://github.com/thchr/Crystalline.jl) (local copy at `../Crystalline`)
**Authors:** Antonio Morales Perez, Thomas Christensen

## Key types and API

### Core pipeline
- `tb_hamiltonian(cbr, Rs; antihermitian)` — top-level entry point; returns `TightBindingModel`
- `obtain_symmetry_related_hoppings(Rs, br_a, br_b)` — enumerates hopping orbits
- `sgrep_induced_by_siteir(br, op)` — site-symmetry induced space group representation

### Types (defined in `src/types.jl`)
- `HoppingOrbit{D}` — orbit of symmetry-related hopping vectors {delta_i}
- `TightBindingBlock{D}` — single block of the Hamiltonian (br1 -> br2 hopping)
- `TightBindingTerm{D}` — block embedded in full matrix, with hermiticity info
- `TightBindingModel{D}` — collection of terms; functor `tbm(cs)` -> parameterized model
- `ParameterizedTightBindingModel{D}` — model with coefficients; functor `ptbm(k)` -> H(k)

### Analysis tools
- `spectrum(ptbm, ks)` — band eigenvalues over k-path (`src/spectrum.jl`)
- `symmetry_eigenvalues(ptbm, ops, k, sgreps)` — irrep content at high-symmetry k (`src/symmetry_analysis.jl`)
- `collect_compatible(ptbm)` / `collect_irrep_annotations(ptbm)` — band symmetry labels
- `berrycurvature(ptbm, k, n)` / `chern(ptbm, n, Nk)` / `chern_fukui(ptbm, n, Nk)` (`src/berry.jl`)
- `gradient_wrt_hopping` / `gradient_wrt_momentum` (`src/gradients.jl`)
- `subduced_complement(tbm, sgnum_H)` — new terms from symmetry breaking (`src/symmetry_breaking.jl`)

### Utilities
- `pin_free!(brs, idx2abc)` — fix free Wyckoff parameters (`src/utils.jl`)
- `solve(ptbm, k; bloch_phase)` — eigenvalues + eigenvectors (in `src/types.jl`)
- `fit(tbm, E_ref, ks)` — least-squares fitting via Optim.jl extension

### Extensions
- `SymmetricTightBindingMakieExt` — Makie recipes for hopping orbits and band structures
- `SymmetricTightBindingOptimExt` — model fitting via Optim.jl (multi-start LBFGS)

## Fourier convention

The package uses **Convention 1** (PythTB-style) throughout: the Bloch basis includes
position phases, i.e., `exp(ik*(t + q_alpha))`. This differs from much of the literature
(Convention 2, lattice-phase only). See `docs/src/theory.md` Appendix A and
`devdocs/fourier.md`. The `solve(...; bloch_phase=Val(true))` option converts eigenvectors
to Convention 2.

## Project structure

```
src/
SymmetricTightBinding.jl # module definition, exports, constants
types.jl # core data structures + evaluation functors
tightbinding.jl # constraint pipeline: M-matrix, nullspace, sparsification
site_representations.jl # coset-decomposition-based induced representations
symmetry_analysis.jl # irrep content at high-symmetry k-points
spectrum.jl # band eigenvalue computation
berry.jl # Berry curvature, Chern numbers (Kubo + Fukui)
gradients.jl # dH/dc_i and dH/dk_i
hermiticity.jl # hermiticity/anti-hermiticity constraint intersection
timereversal.jl # TRS constraint: H(k) = H*(-k)
zassenhaus.jl # Zassenhaus algorithm for subspace intersection
symmetry_breaking.jl # subduced complement for translationengleiche subgroups
utils.jl # orbital positions, pin_free!, split_complex, etc.
show.jl # pretty-printing for all types
ext/
SymmetricTightBindingMakieExt.jl # Makie visualization recipes
SymmetricTightBindingOptimExt.jl # Optim.jl fitting
test/
runtests.jl # test runner
pg_tb_hamiltonian.jl # plane group tests (graphene only)
sg_tb_hamiltonian.jl # space group tests (empty / TODO)
site_representations.jl # representation matrix tests
symmetry-breaking.jl # subduced complement tests
symmetry_analysis.jl # commented out in runtests.jl (broken)
berry.jl # Berry curvature + Chern number tests
docs/src/
tutorial.md # graphene walkthrough
theory.md # mathematical framework (polished)
band-symmetry.md # symmetry analysis example
symmetry-breaking.md # symmetry reduction example
berry.md # Haldane model, Chern numbers
devdocs/
devdocs.md # early developer notes (partially outdated)
docs.md # detailed derivations (superset of devdocs.md)
fourier.md # Convention 1 vs 2 explanation
trs_notes.md # time-reversal symmetry derivations
```

## Running tests

```bash
cd /path/to/SymmetricTightBinding
julia --project -e 'using Pkg; Pkg.test()'
```

Or interactively:
```julia
using Pkg; Pkg.activate(".")
include("test/runtests.jl")
```

Tests take ~1-2 minutes. The `symmetry_analysis.jl` tests are commented out in
`runtests.jl` because they currently fail (see "Known issues" below).

## Known issues

1. **Symmetry analysis failures (PR #89 / treat as issue):** `collect_compatible` returns
incorrect irrep labels for many space groups, especially at K/KA/H/HA points with
3-fold symmetry. Root cause: unresolved phase convention ambiguity in the Theta_G factor
within `symmetry_eigenvalues`. Conjugating the phase fixes some cases but breaks others.
Related to Crystalline.jl issue #12 (sign in `calc_bandreps`).

2. **ANTIHERMITIAN `solve` not implemented** (`src/types.jl:455`).

3. **Performance** (issue #44): `tb_hamiltonian` is slow for high space group numbers
(SG ~200+ can take minutes per EBR).

4. **Test coverage at 55%:** No tests for extensions, `show` methods, `spectrum`, or
`symmetry_analysis` (the latter is commented out). `sg_tb_hamiltonian.jl` is empty.

## Improvement plan

See `PLAN.md` for the phased work plan (TODO audit, devdocs restructuring, tests,
refactoring, symmetry analysis fix).

## Code conventions and preferences

- Follow existing docstring style (see e.g. `HoppingOrbit`, `TightBindingBlock` in `types.jl`)
- Use Unicode math where it improves readability (e.g., `δ`, `ρ`, `Θ`)
- Numeric tolerances are defined as module-level constants (`NULLSPACE_ATOL_DEFAULT`, etc.)
- The codebase uses Convention 1 Fourier transform everywhere; be careful with phases
- Prefer using Crystalline.jl's API over reimplementing group-theoretic operations
- Don't add new functionality without tests
- Always run tests after making changes
- Keep comments brief but include enough detail for non-obvious physics/math
- Work in separate branches for each groupable change (for PR review with collaborators)
203 changes: 203 additions & 0 deletions PLAN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
# SymmetricTightBinding.jl — Improvement plan

A plan for refactoring, testing, documentation, and bug-fixing work on
SymmetricTightBinding.jl. Work is a collaboration between Thomas Christensen and Antonio
Morales. Each phase is worked in a separate branch and PR'd for review.

Status key: `[ ]` = not started, `[~]` = in progress, `[x]` = done

---

## Phase 1: CLAUDE.md `[x]`

**Branch:** `main` (committed directly)

Created `CLAUDE.md` summarizing API, project structure, conventions, known issues, and
developer preferences.

---

## Phase 2: TODO audit `[ ]`

**Branch:** `cleanup/todo-audit`

Catalog all TODOs in the codebase, distinguish big-picture items from minor nits, and
document them. Remove or resolve any that are trivially fixable.

### TODOs found

| Location | Text | Category |
|---|---|---|
| `src/types.jl:223` | Could use knowledge that `-delta` is in orbit | Minor optimization |
| `src/types.jl:455` | ANTIHERMITIAN model `solve` not implemented | **Feature gap** |
| `src/symmetry_analysis.jl:112,117` | Preallocate Theta_G; avoid allocations | Performance nit |
| `ext/MakieExt.jl:50` | Actually do Observable updates in recipe | Feature gap |
| `ext/MakieExt.jl:336` | How to pass kwargs with Makie SpecApi | Minor API gap |
| `ext/OptimExt.jl:142` | Improve initial guess in fitting | Enhancement |
| `test/sg_tb_hamiltonian.jl:6` | Implement 3D space group tests | **Major test gap** |
| `test/pg_tb_hamiltonian.jl:51,56` | Finish structure test; add more PG cases | **Test gap** |

### Big-picture items to track

1. ANTIHERMITIAN `solve` (and downstream spectrum/analysis support)
2. 3D space group Hamiltonian tests (file is empty)
3. More plane group test cases beyond graphene
4. Symmetry analysis correctness (Phase 6)
5. Performance for high SG numbers (issue #44)

### Deliverable

Update CLAUDE.md with the above. File a GitHub issue collecting the big-picture items.
Remove/resolve trivially fixable TODOs. No functional code changes.

---

## Phase 3: Devdocs restructuring `[ ]`

**Branch:** `docs/devdocs-restructure`

### Current state

- `devdocs/devdocs.md` — early notes; photonic framing; strict subset of `docs.md`
- `devdocs/docs.md` — most complete derivation; photonic framing; incomplete hermiticity section
- `devdocs/fourier.md` — short, focused; Convention 1 vs 2
- `devdocs/trs_notes.md` — co-representation theory; heavy overlap with `docs.md`
- `docs/src/theory.md` — polished user-facing synthesis; no photonic framing

### Plan

Move devdocs into the Documenter tree at `docs/src/devdocs/` so they live alongside the
user-facing docs but remain developer-oriented.

**Step 1 — Tidy and consolidate:**
- Delete `devdocs/devdocs.md` (fully superseded by `docs.md`)
- Move remaining files to `docs/src/devdocs/`
- Rename `docs.md` -> `derivations.md`; strip photonic-specific framing; fill in the
incomplete hermiticity section
- Merge `trs_notes.md` content into `derivations.md` as a co-representations section
(the unique content `trs_notes.md` adds is the Wigner/Frobenius classification and
the W = V * Lambda^{1/2} * V^T trick for physically real forms)
- Keep `fourier.md` as-is (it's focused and self-contained)
- Add a short `docs/src/devdocs/README.md` explaining what each file covers

**Step 2 — Cross-link:**
- Add references from `docs/src/theory.md` to the devdocs for readers wanting more detail
- Ensure `docs/make.jl` includes the devdocs pages (if desired in built docs) or excludes
them intentionally

**Principle:** `docs/src/theory.md` = interested-user-facing exposition;
`docs/src/devdocs/` = developer reference for conventions, derivations, and physics details.

---

## Phase 4: Tests & coverage `[ ]`

**Branch:** `tests/coverage-improvements`

Current coverage: 55%. One branch for all test improvements.

### 4A: `spectrum` tests (easy win)
- `spectrum(ptbm, ks)` returns correct shape (Nk x N)
- Eigenvalues at Gamma match direct `eigvals(Hermitian(ptbm([0,0])))`
- Use existing graphene model from `pg_tb_hamiltonian.jl`

### 4B: `show` method tests
- `sprint(show, obj)` for `HoppingOrbit`, `TightBindingBlock`, `TightBindingTerm`,
`TightBindingModel`, `ParameterizedTightBindingModel`
- Verify no errors and basic content presence (e.g., check for expected substrings)

### 4C: Symmetry analysis tests
- Add the two graphene examples from PR #89 (plane group 17) as proper `@test` assertions
— these are known to pass
- Run the full EBR scan from PR #89 offline to identify which cases currently pass; add
those as `@test`
- Pick a curated subset of failing cases (preferring simpler/lower-dimensional groups;
representatives from each failure class) and add as `@test_broken`
- Uncomment `include("symmetry_analysis.jl")` in `runtests.jl`

### 4D: Docs examples as tests
- `docs/src/tutorial.md` graphene example: add spectrum evaluation check (partially covered
already in `pg_tb_hamiltonian.jl`)
- `docs/src/band-symmetry.md`: covered by 4C above
- `docs/src/symmetry-breaking.md`: already covered in `test/symmetry-breaking.jl`
- `docs/src/berry.md`: already well-covered in `test/berry.jl`

### 4E: Extension tests (requires extra deps in test env)
- `test/ext_optim.jl`: test `fit` on Haldane model with known target coefficients; verify
recovery within tolerance
- Makie extension: smoke test only (call `plot`, check no error); may skip if CI display
setup is too annoying

### 4F: More plane/space group Hamiltonian tests
- Add 2-3 more plane group cases to `pg_tb_hamiltonian.jl` (e.g., p4mm, p3)
- Add at least one 3D space group case to `sg_tb_hamiltonian.jl` (e.g., SG 221 / Pm-3m,
which already has handwritten reps in `test/site_representations.jl`)

---

## Phase 5: Maintenance & refactoring `[ ]`

**Branch:** `refactor/cleanup`

Done *after* Phase 4 so tests catch regressions. Incremental, file-by-file review.

### Areas to examine

- **Code duplication in `tightbinding.jl`:** the constraint matrix assembly functions
(`representation_constraint_matrices`, `reciprocal_constraints_matrices`,
`constraint_hermiticity`) share structural patterns that may be factorable
- **Dead/outdated comments:** several reference early development or photonic context
- **`types.jl` `_getindex` logic:** the pretty-printing path is complex; see if it can be
simplified without losing functionality
- **`show.jl`:** review for unnecessary complexity
- **Crystalline.jl API check:** verify we're not reimplementing functions that exist upstream
(orbit handling, translation utilities, etc.)
- **Unused code:** any functions that are defined but never called

### Approach

Read each source file carefully, propose changes, verify tests pass after each change.
Keep refactoring PRs small and reviewable.

---

## Phase 6: Symmetry analysis correctness (PR #89) `[ ]`

**Branch:** new branch (or continue from `symeigs-test`)

The hardest problem. `symmetry_eigenvalues` returns incorrect irrep labels at many
high-symmetry k-points, especially K/KA/H/HA (3-fold symmetry).

### Root cause hypothesis

The Theta_G phase factor `exp(-2*pi*i * G * q_i)` in `symmetry_eigenvalues` has a
sign/convention mismatch. Conjugating the phase fixes K-point failures but introduces new
ones elsewhere — so it's not a simple sign flip.

### Approach

**Step 1 — Anchor on a minimal test case:**
- Plane group 13, EBR `(1c|A)`, on-site only (zero hopping range)
- All space group representations are the identity, so the only source of non-trivial
irreps is Theta_G
- Hand-compute the expected symmetry eigenvalues and compare with `symmetry_eigenvalues`

**Step 2 — Trace the phase pipeline:**
- Convention 1 Bloch basis definition
- `sgrep_induced_by_siteir` output
- `symmetry_eigenvalues` Theta_G application
- Crystalline.jl's `calc_bandreps` convention (and its issue #12)

**Step 3 — Classify failures:**
- Which k-points are affected?
- Is the pattern consistent (e.g., always complex-conjugated)?
- Are there cases where the *structure* of the symmetry vector is wrong (not just permuted
labels)?

**Step 4 — Fix and validate:**
- Propose a fix (may involve changes in both SymmetricTightBinding and Crystalline)
- Run the full EBR scan to verify; convert `@test_broken` from Phase 4C to `@test`

### Relevant upstream issues
- Crystalline.jl issue #12 (sign convention in `calc_bandreps`)
- Possibly other Crystalline.jl issues identified during Step 2
Loading