DKX
Differentiable neoclassical transport for stellarators and tokamaks, in JAX.
DKX solves the radially local, linearized drift-kinetic equation on a flux surface and returns particle and heat fluxes, parallel flows, bootstrap current, transport matrices and ambipolar radial electric fields. It implements the SFINCS Fortran v3 model, including full Fokker–Planck collisions and Phi1, reads and writes SFINCS decks, runs on CPU or GPU, and every output is differentiable in every input.
Install
pip install dkx # CPU
pip install -U "jax[cuda12]" # add for NVIDIA GPUs
Run
import dkx
case = dkx.Case.from_mapping({ # analytic tokamak, teaching grid: seconds, not converged
"schema": 1, "name": "tokamak", "run": {"workflow": "profile", "progress": False},
"geometry": {"format": "analytic", "file": "tokamak", "surfaces": [0.16, 0.25, 0.36]},
"species": [{"name": "deuterium", "charge": 1, "mass_amu": 2.014,
"density_m3": [8.0e19, 7.0e19, 6.0e19], "temperature_keV": [1.0, 0.8, 0.6]}],
"physics": {"model": "full_local", "collisions": "pitch_angle_scattering", "magnetic_drifts": "dkes", "phi1": "off"},
"electric_field": {"mode": "prescribed", "value_kV_m": 0.0},
"resolution": {"theta": 9, "zeta": 1, "pitch": 8, "speed": 4}, "solver": {"method": "auto", "relative_tolerance": 1e-8},
})
result = dkx.run(case)
print("solver route:", result.metadata["solver_route"])
print("particle flux:", float(result.arrays["particle_flux_m2_s"][1, 0]))
From the shell: dkx run case.toml, dkx converge case.toml (check the resolution before
trusting a number), dkx wout_w7x.nc, or dkx input.namelist for a SFINCS deck.
Gradients
import jax, jax.numpy as jnp, dkx
case = dkx.Case.from_file("examples/05_ambipolar_profile/case.toml")
problem = dkx.prepare_er_scan(case, surface_index=1) # geometry, grids, collisions once
def bootstrap_current(er_kv_m):
scan = dkx.batched_er_scan(problem, er_kv_m, differentiable=True, retain_full_state=True)
return jnp.sum(scan.moments["FSABjHat"])
j, dj_der = jax.jit(jax.value_and_grad(bootstrap_current))(jnp.array([-0.2, 0.0, 0.2]))
The derivative passes through the linear solve by the implicit function theorem, and every returned state has satisfied the original kinetic equation. Profiles and geometry differentiate the same way: differentiability.
Choose a workflow
| Calculation | Start from |
|---|---|
Tokamak profile with prescribed E_r |
examples/01_tokamak_profile |
| Stellarator from VMEC or Boozer files | examples/02_vmec_stellarator, examples/03_boozer_stellarator |
| Monoenergetic transport scan | examples/04_monoenergetic_scan |
| Ambipolar roots and branch selection | examples/05_ambipolar_profile |
| Resolution study, gradient checks | examples/06_convergence_certificate, examples/07_gradients |
| Geometry sensitivity and descent (analytic proxy) | examples/08_vmex_optimization |
| Phi1 and impurities (expert path) | examples/09_phi1_and_impurities |
Why DKX
| DKX | SFINCS v3 | MONKES | yancc | |
|---|---|---|---|---|
| Full linearized Fokker–Planck, multispecies | ✅ | ✅ | ❌ | ✅ |
Analytic, VMEC, Boozer and lasym geometry |
✅ | ✅ | ✅ | ✅ |
Phi1 quasineutrality; Tangential magnetic drifts; export_f |
✅ | ✅ | ❌ | ❌ |
Ambipolar E_r root with retained branch evidence |
✅ | ✅ | ❌ | ❌ |
| Transport matrices (RHSMode 2/3) and SFINCS deck/HDF5 I/O | ✅ | ✅ | ❌ | ❌ |
| GPU, JIT-compiled scans, Krylov recycling | ✅ | ❌ | ❌ | ✅ |
| Exact gradients of any output w.r.t. any input | ✅ | adjoint branches | ❌ | claimed |
| Gradients verified against finite differences | ✅ |
Verified
Against SFINCS Fortran v3 on 38 upstream decks with the same discretization, DKX
agrees to solver tolerance: median 4e-6, full Fokker–Planck decks to 1e-8. Against the
independent codes MONKES and YANCC, the four Beidler-normalized monoenergetic coefficients
agree within 6 percent and D33 within 0.1 percent on three configurations. Gradients
agree with central finite differences over a step window on every shipped derivative
example. Details, tolerances and scope: validation matrix.
Fast
HSX_PASCollisions_DKESTrajectories, RHSMode=1, 744,610 unknowns, one machine, against the
PETSc 3.23 / MUMPS 5.8.2 build of SFINCS v3. Warm is the second solve in a process, after XLA has compiled.
| Configuration | Warm solve | Peak RSS |
|---|---|---|
DKX, Nxi-for-x ramp |
27.2 s | 0.93 GB |
DKX, uniform Nxi |
44.3 s | 1.16 GB |
| DKX, RTX A4000 GPU | 45.0 s | — |
| SFINCS Fortran v3, 1 rank | 463.6 s | 3.98 GB |
| SFINCS Fortran v3, 2 ranks (its best) | 229.5 s | 2.86 GB |
| Cold versus warm, M3 Max CPU | Unknowns | Cold | Warm |
|---|---|---|---|
| HSX PAS reduced | 40,584 | 1.72 s | 0.12 s |
HSX PAS, 25x51x100x5 |
744,610 | 23.6 s | 20.0 s |
That is one measured 744k-unknown HSX PAS case, chosen because DKX has an exact structured solver for it. Across all 38 upstream decks: structured route faster on 9 of 9; Krylov route faster on 7 of 23, six not completed. Every deck, hardware string and method: performance.
Documentation
Tutorial: first W7-X result · How-to: resolution, wout files, SFINCS decks · Reference: schema, CLI, API · Explanation: physics models, solver routes, limitations
Cite
@software{dkx,
author = {Jorge, Rogerio and contributors},
title = {DKX: differentiable drift-kinetic neoclassical transport in JAX},
url = {https://github.com/uwplasma/DKX},
year = {2026}
}
Please also cite SFINCS (Landreman, Smith, Mollén & Helander, Phys. Plasmas 21, 042503, 2014) when you use its decks or model. Metadata: CITATION.cff.
Examples · Research plan · Contributing · SOLVAX owns the reusable solver algorithms · LICENSE
Metadata
Release files for dkx 2.5.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| dkx-2.5.0.tar.gz | 1.1 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| dkx-2.5.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 1.7 MB
Release files / dkx-2.5.0.tar.gz
| Download URL | dkx-2.5.0.tar.gz |
|---|---|
| Size | 1.1 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
06565eedf17b38ebb5e317d4f3a19e44e2bd44d3ab92d01f0344b66402880ca6
|
|
BLAKE2b-256 checksum How to use checksums |
4daca8cb96a2c2641b7db19257b0b4c74eba5f46b126f740a1f91a971ba2f20e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 20, 2026.
Transparency logRelease files / dkx-2.5.0-py3-none-any.whl
| Download URL | dkx-2.5.0-py3-none-any.whl |
|---|---|
| Size | 608.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
f236682085f33b1abc61a458d12f2d9d0c182d793431b4a8999dce8a44f761e4
|
|
BLAKE2b-256 checksum How to use checksums |
015466edfdf57bcf7df6fc55fef2625103a0198d11d958504b67686eb256c4d3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 20, 2026.
Transparency log