Metadata-Version: 2.4
Name: danf
Version: 0.5.0
Summary: Differential Algebra Normal Forms for symplectic maps
Author-email: Eremey Valetov <evv@msu.edu>
License: MIT
Project-URL: Repository, https://github.com/evvaletov/danf
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: daceypy>=1.3.0
Requires-Dist: numpy>=1.24

# DANF

Differential Algebra Normal Forms for symplectic maps, built on [DACEyPy](https://github.com/giovannipurpura/daceypy).

Computes amplitude-dependent tune shifts (detuning), chromaticity, and the
complex-basis normal form of nonlinear symplectic maps via order-by-order
elimination in the complex eigenvector basis.

## Installation

```bash
pip install danf
```

## Quick start

```python
import numpy as np
from daceypy import DA
from danf import NormalForm
from danf.elements import rotation, thin_sext, compose

# Initialize DA engine: order 7, 2 variables (x, px)
DA.init(7, 2)

# Build a one-turn map: rotation (tune 0.31) + sextupole kick (k2L = 1.0)
one_turn = compose(rotation(0.31), thin_sext(1.0))

nf = NormalForm(one_turn)
nf.compute()

print(f"Tune: {nf.tunes[0]:.6f}")
print(f"dnu/dJ: {nf.detuning['dnux_dJx']:.8f}")
```

## API

### `NormalForm(da_map)`

The central class. Accepts a 2-, 4-, or 6-component DA map (1-, 2-, or 3-DOF).

- `nf.compute()` — run the full computation.
- `nf.tunes` — linear tunes, one per DOF.
- `nf.detuning` — amplitude-dependent tune-shift dict.
  - 1-DOF keys: `dnux_dJx`, `alpha_xx`, `c21`.
  - 2-DOF keys: `dnux_dJx`, `dnux_dJy`, `dnuy_dJx`, `dnuy_dJy`, plus the complex
    order-3 coefficients `c21_xx`, `c21_xy`, `c21_yx`, `c21_yy`.
- `nf.nf_map` — the post-transformation Floquet normal-form map (real-coord DA).
- `nf.to_complex_basis(plane=0)` — `{(k, l): complex}` for `z = (x - i*px)/√2`.
- `nf.driving_terms(plane=0, tol=1e-12)` — non-Birkhoff (`k - l ≠ 1`)
  coefficients only; empty to tolerance away from resonance.

### `chromaticity_1d(da_map)`

Linear and higher-order chromaticity from a 1-DOF map built with one or more
passive parameters (e.g. `δ` as the third DA variable via `DA.init(N, 3)`).

```python
from daceypy import DA
from danf import chromaticity_1d

DA.init(5, 3)  # 1 DOF + δ as DA(3)
x, px, delta = DA(1), DA(2), DA(3)
mu = 2*np.pi*(0.28 + 1.5*delta - 3.0*delta*delta)
xr  =  x*mu.cos() + px*mu.sin()
axr = -x*mu.sin() + px*mu.cos()

chrom = chromaticity_1d([xr, axr - 0.5*xr*xr])
print(chrom.tune)            # 0.28
print(chrom.dnu_ddelta())    # 1.5
print(chrom.d2nu_ddelta2())  # -6.0
```

### `danf.elements`

DA-map convenience functions: `rotation`, `thin_quad`, `thin_sext`, `thin_oct`,
`drift`, `compose`.

### `compute_detuning_1d(da_x, da_px, tune)`

Low-level 1-D normal-form primitive; returns `(dnu_dJ, c21, nf_x, nf_px)`. Use
`NormalForm` for the standard path.

## Cross-validation

DANF's numerical output is regression-tested against COSY INFINITY v10.2
(`DANF` and `TS` commands) to 10–12 significant figures on:

| Quantity                              | Agreement |
|---------------------------------------|-----------|
| Linear tune, 1-DOF                    | `< 1e-14` |
| `dnu/dJ`, 1-DOF sextupole map         | `< 1e-10` |
| `dnu_x/dJ_x`, `dnu_x/dJ_y`, 2-DOF     | `< 1e-10` |
| `dnu/ddelta`, `d²nu/ddelta²` (chrom.) | `< 1e-10` |
| Birkhoff `c_{2,1}` complex coeff      | `< 1e-10` |

## License

MIT
