# Plan: 2D/3D-Dichten + MO-Koeffizienten (BCSR)

## Ziele
- 2D/3D-Gitterdaten (z. B. Elektronendichte) effizient speichern.
- MO-/Wellenfunktions-Koeffizienten aus CP2K effizient und robust komprimieren.
- Reproduzierbarkeit, Random Access und Delta-Encoding der bestehenden TACO-Pipeline erhalten.

---

## Teil A: 2D/3D-Dichtefelder (Grid-Daten)

### A1) Datenmodell & Metadaten
**Neues Header-Schema für Extra-Datasets** (pro Dataset):
- `name`: eindeutiger Key (z. B. `rho`, `spin_density`)
- `ndim`, `shape`
- `dtype` (mind. `f32`/`f64`)
- **Grid-Metadaten**:
  - `origin`: `[f64; 3]`
  - `spacing`: `[f64; 3]`
  - `axis_order`: z. B. `xyz`
  - `units`
- **Codec-Spezifikation**:
  - `codec`: `fpzip` oder `zstd` (fallback)
  - `fpzip.prec`: Bit-Precision (z. B. 16–24)
  - optional: `full_frame_interval` für Grid-Deltas

**Hinweis:** `FrameData.extra` bleibt API-seitig bestehen, der Header steuert die Kodierung.

### A2) Codec-Strategie (fpzip-rs)
- **Standard**: `fpzip` für f32/f64, 2D/3D (pure Rust).
- **Fallback**: bestehende `zstd`-Pipeline für nicht unterstützte Typen.

### A3) Encoding-Pipeline
1. `FrameData::delta_from` weiterhin nutzen (zeitliches Delta).
2. Array flatten (ndarray contiguous).
3. `fpzip`-Kompression mit `prec` aus Dataset-Header.
4. Komprimierte Bytes + Länge speichern.

### A4) Decoding-Pipeline
1. Dataset-Header lesen (Codec/Shape).
2. `fpzip` dekomprimieren → f32/f64.
3. Rekonstruktion der Form, dann Delta anwenden.

### A5) Tests & Benchmarks
- Lossless Roundtrip (prec=32/64)
- Lossy Roundtrip (prec=16/20/24) + Metriken (RMSE, max error)
- Vergleich `fpzip` vs. `zstd+f16` auf realen Dichtefeldern

---

## Teil B: MO-Koeffizienten (BCSR + Delta + Zstd)

### B1) Datenmodell
**Empfohlen:** MO-Koeffizienten als `C^T` speichern  
- **Zeilen = MOs**, **Spalten = Basisfunktionen**  
- Vorteil: pro MO meist sparsamer

**BCSR-Struktur**:
- `row_ptr`
- `col_block_indices`
- `block_values` (dichte Blöcke)

**Blockgröße**:
- vorzugsweise nach Atom-/Shell-Grouping in CP2K
- z. B. 4×4 oder blockweise nach Shell-Größen

### B2) Alignment zwischen Frames (kritisch für Delta)
- **Phasen-/Vorzeichen-Alignment** pro Orbital (maximaler Overlap)
- Für degenerierte Subräume: lokale Rotation (Procrustes/SVD)
- Ziel: `C_t` und `C_{t-1}` möglichst „gleich orientiert“

### B3) Delta-Encoding
- Delta **zwischen Frames**: `block_values_t − block_values_{t-1}`
- Indizes:
  - falls Sparsity-Pattern stabil: einmal im Header speichern
  - sonst pro Frame speichern, Indizes zusätzlich delta-kodieren + zstd

### B4) Kompression
- `block_values`: `zstd` (oder optional `fpzip` für float-Blöcke)
- `row_ptr`/`col_indices`: delta-kodiert + `zstd`

### B5) API/Struktur-Entscheidung
**Option 1:** neues `ExtraArray::SparseBCSR`
- klare Typisierung, direkte API
**Option 2:** eigener `WavefunctionData`-Block im `FrameData`
- getrennt von `extra`, explizit für Wellenfunktionen

### B6) Tests & Benchmarks
- Roundtrip-Test mit stabiler Orbital-Zuordnung
- Delta-Chain-Test über mehrere Frames
- Benchmark: Ratio + Fehler vs. dense+fpzip

---

## Milestones (vorgeschlagen)

1. **Header-Schema erweitern**  
   - `ExtraDatasetSpec` + Codec-Info (fpzip/zstd)  
   - Version bump (Formatversion)

2. **fpzip-Integration für Grid-Daten**  
   - Codec-Enum + Implementierung in `FrameData::write/read`

3. **BCSR-Datenstruktur**  
   - Datenmodell + Reader/Writer für BCSR  
   - Tests mit synthetischen MO-Daten

4. **Orbitale Alignment + Delta**  
   - Overlap-basiertes Vorzeichen  
   - (optional) Degenerat-Subspace Rotation

5. **Python/CLI-Expose**  
   - Dataset-Metadaten aus Python  
   - `taco info` zeigt Grid/BCSR-Infos

6. **Benchmark-Suite**  
   - echte CP2K-Daten (Dichte + MOs)
   - Vergleich: `fpzip`, `zstd+f16`, BCSR+zstd

---

## Offene Fragen
- Standard-`prec` für Dichte (z. B. 16 vs. 20 Bit)?
- Müssen Grid-Deltas immer aktiv sein oder nur optional?
- BCSR: feste Blockgröße vs. Shell-basierte variable Blöcke?
- MO-Alignment: wie zuverlässig sind degenerierte Subräume in euren Daten?
