agnimhd 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. agnimhd-0.1.0/.pymon +0 -0
  2. agnimhd-0.1.0/.zenodo.json +13 -0
  3. agnimhd-0.1.0/CITATION.cff +26 -0
  4. agnimhd-0.1.0/LICENSE +21 -0
  5. agnimhd-0.1.0/MANIFEST.in +12 -0
  6. agnimhd-0.1.0/PKG-INFO +148 -0
  7. agnimhd-0.1.0/README.md +97 -0
  8. agnimhd-0.1.0/pyproject.toml +131 -0
  9. agnimhd-0.1.0/setup.cfg +4 -0
  10. agnimhd-0.1.0/src/agnimhd/__init__.py +52 -0
  11. agnimhd-0.1.0/src/agnimhd/_version.py +24 -0
  12. agnimhd-0.1.0/src/agnimhd/adapters/__init__.py +10 -0
  13. agnimhd-0.1.0/src/agnimhd/adapters/desc.py +139 -0
  14. agnimhd-0.1.0/src/agnimhd/adapters/desc_objective.py +355 -0
  15. agnimhd-0.1.0/src/agnimhd/assemble.py +1212 -0
  16. agnimhd-0.1.0/src/agnimhd/backend.py +87 -0
  17. agnimhd-0.1.0/src/agnimhd/basis/__init__.py +43 -0
  18. agnimhd-0.1.0/src/agnimhd/basis/diffmat.py +957 -0
  19. agnimhd-0.1.0/src/agnimhd/basis/zernike.py +482 -0
  20. agnimhd-0.1.0/src/agnimhd/cli.py +257 -0
  21. agnimhd-0.1.0/src/agnimhd/config.py +302 -0
  22. agnimhd-0.1.0/src/agnimhd/equilibrium.py +724 -0
  23. agnimhd-0.1.0/src/agnimhd/multigpu.py +92 -0
  24. agnimhd-0.1.0/src/agnimhd/objective.py +912 -0
  25. agnimhd-0.1.0/src/agnimhd/plotting.py +474 -0
  26. agnimhd-0.1.0/src/agnimhd/py.typed +0 -0
  27. agnimhd-0.1.0/src/agnimhd/quadrature.py +284 -0
  28. agnimhd-0.1.0/src/agnimhd/solvers.py +857 -0
  29. agnimhd-0.1.0/src/agnimhd/sources.py +81 -0
  30. agnimhd-0.1.0/src/agnimhd/symmetry.py +119 -0
  31. agnimhd-0.1.0/src/agnimhd.egg-info/PKG-INFO +148 -0
  32. agnimhd-0.1.0/src/agnimhd.egg-info/SOURCES.txt +36 -0
  33. agnimhd-0.1.0/src/agnimhd.egg-info/dependency_links.txt +1 -0
  34. agnimhd-0.1.0/src/agnimhd.egg-info/entry_points.txt +2 -0
  35. agnimhd-0.1.0/src/agnimhd.egg-info/requires.txt +39 -0
  36. agnimhd-0.1.0/src/agnimhd.egg-info/scm_file_list.json +118 -0
  37. agnimhd-0.1.0/src/agnimhd.egg-info/scm_version.json +8 -0
  38. agnimhd-0.1.0/src/agnimhd.egg-info/top_level.txt +1 -0
agnimhd-0.1.0/.pymon ADDED
Binary file
@@ -0,0 +1,13 @@
1
+ {
2
+ "title": "agnimhd: a differentiable finite-n ideal MHD stability solver",
3
+ "upload_type": "software",
4
+ "description": "AGNI computes the most unstable finite-n ideal MHD mode of a 3D equilibrium: it discretizes the energy principle on a straight-field-line grid and returns the squared growth rate of the most unstable mode and its derivative with respect to the equilibrium's parameters, for optimization through equilibrium codes such as DESC.",
5
+ "creators": [
6
+ {"name": "Gaur, Rahul"}
7
+ ],
8
+ "license": "MIT",
9
+ "keywords": ["plasma physics", "MHD stability", "stellarator", "tokamak", "JAX", "differentiable"],
10
+ "related_identifiers": [
11
+ {"identifier": "10.48550/arXiv.2608.01750", "relation": "isSupplementTo", "resource_type": "publication-preprint", "scheme": "doi"}
12
+ ]
13
+ }
@@ -0,0 +1,26 @@
1
+ cff-version: 1.2.0
2
+ message: "If you use agnimhd, please cite the AGNI paper."
3
+ title: "agnimhd"
4
+ repository-code: "https://github.com/rahulgaur104/AGNI"
5
+ license: MIT
6
+ authors:
7
+ - family-names: Gaur
8
+ given-names: Rahul
9
+ preferred-citation:
10
+ type: article
11
+ title: "AGNI: A differentiable MHD stability solver & optimizer for magnetic confinement fusion devices"
12
+ authors:
13
+ - family-names: Gaur
14
+ given-names: Rahul
15
+ - family-names: Patil
16
+ given-names: Sanket
17
+ - family-names: Gupta
18
+ given-names: Prateek
19
+ - family-names: Patch
20
+ given-names: Djin
21
+ - family-names: Qian
22
+ given-names: Tony
23
+ year: 2026
24
+ journal: "arXiv preprint arXiv:2608.01750"
25
+ doi: "10.48550/arXiv.2608.01750"
26
+ url: "https://arxiv.org/abs/2608.01750"
agnimhd-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Rahul Gaur
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,12 @@
1
+ # The sdist carries the package and what describes it; the test data, examples,
2
+ # benchmarks, figures and the paper stay in the repository.
3
+ include README.md LICENSE CITATION.cff pyproject.toml
4
+ graft src
5
+ prune tests
6
+ prune examples
7
+ prune benchmarks
8
+ prune docs
9
+ prune tools
10
+ global-exclude __pycache__ *.py[cod]
11
+ prune .github
12
+ exclude .flake8 .gitignore .pre-commit-config.yaml .test_durations mkdocs.yml
agnimhd-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,148 @@
1
+ Metadata-Version: 2.4
2
+ Name: agnimhd
3
+ Version: 0.1.0
4
+ Summary: AGNI: differentiable finite-n ideal MHD stability solver
5
+ Author-email: Rahul Gaur <rgaur@terpmail.umd.edu>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/rahulgaur104/AGNI
8
+ Project-URL: Issues, https://github.com/rahulgaur104/AGNI/issues
9
+ Project-URL: Paper, https://arxiv.org/abs/2608.01750
10
+ Project-URL: Documentation, https://rahulgaur104.github.io/AGNI/
11
+ Keywords: plasma,mhd,stability,stellarator,tokamak,jax
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Science/Research
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Topic :: Scientific/Engineering :: Physics
16
+ Requires-Python: >=3.12
17
+ Description-Content-Type: text/markdown
18
+ License-File: LICENSE
19
+ Requires-Dist: jax>=0.4.30
20
+ Requires-Dist: numpy>=1.24
21
+ Requires-Dist: scipy>=1.10
22
+ Requires-Dist: matfree>=0.6.2
23
+ Provides-Extra: hdf5
24
+ Requires-Dist: h5py>=3.0; extra == "hdf5"
25
+ Provides-Extra: plot
26
+ Requires-Dist: matplotlib>=3.7; extra == "plot"
27
+ Provides-Extra: multigpu
28
+ Requires-Dist: jaxmg; extra == "multigpu"
29
+ Provides-Extra: test
30
+ Requires-Dist: pytest>=7.0; extra == "test"
31
+ Requires-Dist: pytest-cov>=4.0; extra == "test"
32
+ Requires-Dist: pytest-split>=0.8; extra == "test"
33
+ Requires-Dist: pytest-mpl>=0.16; extra == "test"
34
+ Provides-Extra: benchmark
35
+ Requires-Dist: pytest-benchmark>=4.0; extra == "benchmark"
36
+ Provides-Extra: dev
37
+ Requires-Dist: agnimhd[hdf5,plot,test]; extra == "dev"
38
+ Requires-Dist: black>=24.0; extra == "dev"
39
+ Requires-Dist: flake8>=7.0; extra == "dev"
40
+ Requires-Dist: isort>=5.13; extra == "dev"
41
+ Requires-Dist: pre-commit>=3.5; extra == "dev"
42
+ Provides-Extra: docs
43
+ Requires-Dist: mkdocs>=1.5; extra == "docs"
44
+ Requires-Dist: mkdocs-material>=9.5; extra == "docs"
45
+ Requires-Dist: mkdocstrings[python]>=0.24; extra == "docs"
46
+ Requires-Dist: mkdocs-jupyter>=0.24; extra == "docs"
47
+ Provides-Extra: notebooks
48
+ Requires-Dist: nbmake>=1.5; extra == "notebooks"
49
+ Requires-Dist: ipykernel>=6; extra == "notebooks"
50
+ Dynamic: license-file
51
+
52
+ # agnimhd
53
+
54
+ [![CI](https://github.com/rahulgaur104/AGNI/actions/workflows/ci.yml/badge.svg)](https://github.com/rahulgaur104/AGNI/actions/workflows/ci.yml)
55
+ [![docs](https://github.com/rahulgaur104/AGNI/actions/workflows/docs.yml/badge.svg)](https://rahulgaur104.github.io/AGNI/)
56
+ [![PyPI](https://img.shields.io/pypi/v/agnimhd)](https://pypi.org/project/agnimhd/)
57
+
58
+ AGNI is a differentiable finite-n ideal MHD stability solver. It discretizes the
59
+ ideal MHD energy principle on a straight-field-line grid and returns the squared
60
+ growth rate of the most unstable mode (positive: unstable) and its gradient. It
61
+ computes the stability objective; it does not run an optimization itself.
62
+
63
+ The package is under active development, and the API, the file format and the
64
+ numerics change without notice. For a stable version use the AGNI
65
+ implementation inside DESC,
66
+ [PR #1893](https://github.com/PlasmaControl/DESC/pull/1893), branch
67
+ `rg/AGNI_var`.
68
+
69
+ ## Quick start
70
+
71
+ Stability of a DESC equilibrium (needs DESC installed):
72
+
73
+ ```bash
74
+ agnimhd solve my_equilibrium.h5 --res 24,12,8
75
+ ```
76
+
77
+ prints `gamma^2` for each toroidal mode family `n = x + k NFP`, all solved on
78
+ one field period, and names the most unstable.
79
+
80
+ From Python:
81
+
82
+ ```python
83
+ import agnimhd
84
+
85
+ basis = agnimhd.Basis(24, 12, 8) # n_zeta = 8 per field period
86
+ eq, diffmat = agnimhd.from_desc("my_equilibrium.h5", basis, family=0)
87
+ gamma2 = agnimhd.growth_rate(eq, diffmat) # gamma^2 = -lambda > 0: unstable
88
+ ```
89
+
90
+ `growth_rate` is solve mode and is not differentiable. The gradient comes from
91
+ optimize mode, `jax.grad(agnimhd.growth_rate_of)(params, equilibrium_map,
92
+ diffmat)`, with `equilibrium_map` the equilibrium code's map from its parameters
93
+ to an `EquilibriumData`.
94
+
95
+ Matrices too large for one GPU: `SolverConfig(eigensolver="dense_mg")` splits the
96
+ dense matrix over all GPUs of a node with JAXMg (tested with `jaxmg==0.0.9`);
97
+ 182,784 unknowns in 8.5 minutes on four A100s. See the multi-GPU page of the
98
+ documentation.
99
+
100
+ Two shipped cases run without DESC: `python examples/cross_sections.py`. Other
101
+ codes build an `EquilibriumData` from arrays, or load a saved one with
102
+ `EquilibriumData.load("eq.npz")`. See the
103
+ [documentation](https://rahulgaur104.github.io/AGNI/).
104
+
105
+ ## Install
106
+
107
+ ```bash
108
+ pip install agnimhd # jax, numpy, scipy, matfree
109
+ pip install "agnimhd[hdf5,test]" # HDF5 files and the test suite
110
+ ```
111
+
112
+ Python 3.12. DESC is optional and only needed for `from_desc`. GPU, DESC and
113
+ multi-GPU set-ups: [Installation](https://rahulgaur104.github.io/AGNI/installation/).
114
+
115
+ ## Development
116
+
117
+ ```bash
118
+ pip install -e ".[dev]"
119
+ pre-commit install
120
+ pytest tests -q # about 25 min on one CPU
121
+ ```
122
+
123
+ Releasing: tag `vX.Y.Z` on `master` and publish a GitHub release of it. The
124
+ `release` workflow builds the package from the tag and uploads it to PyPI, and
125
+ Zenodo archives the release with a DOI. The version comes from the tag
126
+ (`setuptools_scm`); nothing in the source is edited.
127
+
128
+ ## Reference
129
+
130
+ R. Gaur, S. Patil, P. Gupta, D. Patch, T. Qian, *AGNI: A differentiable MHD
131
+ stability solver & optimizer for magnetic confinement fusion devices*,
132
+ [arXiv:2608.01750](https://arxiv.org/abs/2608.01750) (2026),
133
+ doi:[10.48550/arXiv.2608.01750](https://doi.org/10.48550/arXiv.2608.01750).
134
+ PDF of v3 in this repository: [docs/paper/agni_arxiv_2608.01750v3.pdf](docs/paper/agni_arxiv_2608.01750v3.pdf).
135
+
136
+ ```bibtex
137
+ @article{gaur2026agni,
138
+ title = {{AGNI}: A differentiable {MHD} stability solver \& optimizer for magnetic confinement fusion devices},
139
+ author = {Gaur, Rahul and Patil, Sanket and Gupta, Prateek and Patch, Djin and Qian, Tony},
140
+ journal = {arXiv preprint arXiv:2608.01750},
141
+ year = {2026},
142
+ doi = {10.48550/arXiv.2608.01750}
143
+ }
144
+ ```
145
+
146
+ Originally developed inside [DESC](https://github.com/PlasmaControl/DESC)
147
+ ([PR #1893](https://github.com/PlasmaControl/DESC/pull/1893), on the
148
+ differentiation matrices of PR #1789). MIT license.
@@ -0,0 +1,97 @@
1
+ # agnimhd
2
+
3
+ [![CI](https://github.com/rahulgaur104/AGNI/actions/workflows/ci.yml/badge.svg)](https://github.com/rahulgaur104/AGNI/actions/workflows/ci.yml)
4
+ [![docs](https://github.com/rahulgaur104/AGNI/actions/workflows/docs.yml/badge.svg)](https://rahulgaur104.github.io/AGNI/)
5
+ [![PyPI](https://img.shields.io/pypi/v/agnimhd)](https://pypi.org/project/agnimhd/)
6
+
7
+ AGNI is a differentiable finite-n ideal MHD stability solver. It discretizes the
8
+ ideal MHD energy principle on a straight-field-line grid and returns the squared
9
+ growth rate of the most unstable mode (positive: unstable) and its gradient. It
10
+ computes the stability objective; it does not run an optimization itself.
11
+
12
+ The package is under active development, and the API, the file format and the
13
+ numerics change without notice. For a stable version use the AGNI
14
+ implementation inside DESC,
15
+ [PR #1893](https://github.com/PlasmaControl/DESC/pull/1893), branch
16
+ `rg/AGNI_var`.
17
+
18
+ ## Quick start
19
+
20
+ Stability of a DESC equilibrium (needs DESC installed):
21
+
22
+ ```bash
23
+ agnimhd solve my_equilibrium.h5 --res 24,12,8
24
+ ```
25
+
26
+ prints `gamma^2` for each toroidal mode family `n = x + k NFP`, all solved on
27
+ one field period, and names the most unstable.
28
+
29
+ From Python:
30
+
31
+ ```python
32
+ import agnimhd
33
+
34
+ basis = agnimhd.Basis(24, 12, 8) # n_zeta = 8 per field period
35
+ eq, diffmat = agnimhd.from_desc("my_equilibrium.h5", basis, family=0)
36
+ gamma2 = agnimhd.growth_rate(eq, diffmat) # gamma^2 = -lambda > 0: unstable
37
+ ```
38
+
39
+ `growth_rate` is solve mode and is not differentiable. The gradient comes from
40
+ optimize mode, `jax.grad(agnimhd.growth_rate_of)(params, equilibrium_map,
41
+ diffmat)`, with `equilibrium_map` the equilibrium code's map from its parameters
42
+ to an `EquilibriumData`.
43
+
44
+ Matrices too large for one GPU: `SolverConfig(eigensolver="dense_mg")` splits the
45
+ dense matrix over all GPUs of a node with JAXMg (tested with `jaxmg==0.0.9`);
46
+ 182,784 unknowns in 8.5 minutes on four A100s. See the multi-GPU page of the
47
+ documentation.
48
+
49
+ Two shipped cases run without DESC: `python examples/cross_sections.py`. Other
50
+ codes build an `EquilibriumData` from arrays, or load a saved one with
51
+ `EquilibriumData.load("eq.npz")`. See the
52
+ [documentation](https://rahulgaur104.github.io/AGNI/).
53
+
54
+ ## Install
55
+
56
+ ```bash
57
+ pip install agnimhd # jax, numpy, scipy, matfree
58
+ pip install "agnimhd[hdf5,test]" # HDF5 files and the test suite
59
+ ```
60
+
61
+ Python 3.12. DESC is optional and only needed for `from_desc`. GPU, DESC and
62
+ multi-GPU set-ups: [Installation](https://rahulgaur104.github.io/AGNI/installation/).
63
+
64
+ ## Development
65
+
66
+ ```bash
67
+ pip install -e ".[dev]"
68
+ pre-commit install
69
+ pytest tests -q # about 25 min on one CPU
70
+ ```
71
+
72
+ Releasing: tag `vX.Y.Z` on `master` and publish a GitHub release of it. The
73
+ `release` workflow builds the package from the tag and uploads it to PyPI, and
74
+ Zenodo archives the release with a DOI. The version comes from the tag
75
+ (`setuptools_scm`); nothing in the source is edited.
76
+
77
+ ## Reference
78
+
79
+ R. Gaur, S. Patil, P. Gupta, D. Patch, T. Qian, *AGNI: A differentiable MHD
80
+ stability solver & optimizer for magnetic confinement fusion devices*,
81
+ [arXiv:2608.01750](https://arxiv.org/abs/2608.01750) (2026),
82
+ doi:[10.48550/arXiv.2608.01750](https://doi.org/10.48550/arXiv.2608.01750).
83
+ PDF of v3 in this repository: [docs/paper/agni_arxiv_2608.01750v3.pdf](docs/paper/agni_arxiv_2608.01750v3.pdf).
84
+
85
+ ```bibtex
86
+ @article{gaur2026agni,
87
+ title = {{AGNI}: A differentiable {MHD} stability solver \& optimizer for magnetic confinement fusion devices},
88
+ author = {Gaur, Rahul and Patil, Sanket and Gupta, Prateek and Patch, Djin and Qian, Tony},
89
+ journal = {arXiv preprint arXiv:2608.01750},
90
+ year = {2026},
91
+ doi = {10.48550/arXiv.2608.01750}
92
+ }
93
+ ```
94
+
95
+ Originally developed inside [DESC](https://github.com/PlasmaControl/DESC)
96
+ ([PR #1893](https://github.com/PlasmaControl/DESC/pull/1893), on the
97
+ differentiation matrices of PR #1789). MIT license.
@@ -0,0 +1,131 @@
1
+ [build-system]
2
+ requires = ["setuptools>=77", "setuptools_scm>=8"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "agnimhd"
7
+ dynamic = ["version"] # from the git tag, by setuptools_scm (as DESC uses versioneer)
8
+ description = "AGNI: differentiable finite-n ideal MHD stability solver"
9
+ readme = "README.md"
10
+ # jax 0.11 declares Requires-Python >= 3.12, and 3.12 is the only interpreter
11
+ # this package has been run on. Claiming 3.10 support would mean shipping
12
+ # against an older jax nobody has tested.
13
+ requires-python = ">=3.12"
14
+ license = "MIT"
15
+ license-files = ["LICENSE"]
16
+ authors = [{ name = "Rahul Gaur", email = "rgaur@terpmail.umd.edu" }]
17
+ keywords = ["plasma", "mhd", "stability", "stellarator", "tokamak", "jax"]
18
+ classifiers = [
19
+ "Development Status :: 3 - Alpha",
20
+ "Intended Audience :: Science/Research",
21
+ "Programming Language :: Python :: 3.12",
22
+ "Topic :: Scientific/Engineering :: Physics",
23
+ ]
24
+
25
+ # EXACTLY these four. DESC appears nowhere -- not as a dependency, not as an
26
+ # optional extra, not in the test extra. The dependency runs the other way:
27
+ # DESC installs agnimhd. See docs/interface.md.
28
+ #
29
+ # `matfree` is REQUIRED, not optional: `from matfree import decomp, eig`
30
+ # supplies the Lanczos tridiagonalization and the shift-invert eigensolve that
31
+ # every matrix-free path uses. It was undeclared in the original DESC pull
32
+ # request, so a clean install raised ModuleNotFoundError at solve time rather
33
+ # than at install time.
34
+ #
35
+ # The 0.6.2 FLOOR IS A CORRECTNESS BOUND, not a preference. Before matfree PR
36
+ # #288 the Arnoldi/Lanczos recurrence orthonormalized with the bilinear form
37
+ # `Q.T @ Q` instead of `Q.conj().T @ Q`. On a real symmetric operator the two
38
+ # coincide and every 3D case is unaffected; on the complex Hermitian operator
39
+ # that `AssemblyConfig(axisym=True)` builds they do not, and the returned Ritz
40
+ # vectors are wrong while the Ritz VALUES stay plausible -- so nothing raises
41
+ # and only the Rayleigh residual shows it. Measured on the shipped QH case at
42
+ # one zeta plane: lam_R = +9.713e-02 against a dense -2.660e-03, residual
43
+ # 1.14e+03. Against 0.6.2 the same solve returns -2.660490917e-03.
44
+ dependencies = [
45
+ "jax>=0.4.30",
46
+ "numpy>=1.24",
47
+ "scipy>=1.10",
48
+ "matfree>=0.6.2",
49
+ ]
50
+
51
+ [project.optional-dependencies]
52
+ # HDF5 serialization only. The native EquilibriumData format is .npz and needs
53
+ # nothing beyond numpy; save_hdf5/load_hdf5 raise an ImportError naming h5py.
54
+ hdf5 = ["h5py>=3.0"]
55
+ # Plotting only. agnimhd.plotting's array-returning functions need nothing
56
+ # beyond the four required dependencies; only the plot_* functions import
57
+ # matplotlib, and they raise a named ImportError if it is absent.
58
+ plot = ["matplotlib>=3.7"]
59
+ # eigensolver="dense_mg": the dense matrix split over several GPUs.
60
+ multigpu = ["jaxmg"]
61
+ # pytest-split is REQUIRED, not optional: ci.yml runs the suite as four
62
+ # `--splits 4 --group N` jobs, and without it every one of them errors on an
63
+ # unrecognized argument.
64
+ test = ["pytest>=7.0", "pytest-cov>=4.0", "pytest-split>=0.8", "pytest-mpl>=0.16"]
65
+ benchmark = ["pytest-benchmark>=4.0"]
66
+ dev = [
67
+ "agnimhd[test,hdf5,plot]",
68
+ "black>=24.0",
69
+ "flake8>=7.0",
70
+ "isort>=5.13",
71
+ "pre-commit>=3.5",
72
+ ]
73
+ docs = [
74
+ "mkdocs>=1.5",
75
+ "mkdocs-material>=9.5",
76
+ "mkdocstrings[python]>=0.24",
77
+ "mkdocs-jupyter>=0.24",
78
+ ]
79
+ notebooks = ["nbmake>=1.5", "ipykernel>=6"]
80
+
81
+ [project.scripts]
82
+ agnimhd = "agnimhd.cli:main"
83
+
84
+ [project.urls]
85
+ Homepage = "https://github.com/rahulgaur104/AGNI"
86
+ Issues = "https://github.com/rahulgaur104/AGNI/issues"
87
+ Paper = "https://arxiv.org/abs/2608.01750"
88
+ Documentation = "https://rahulgaur104.github.io/AGNI/"
89
+
90
+ [tool.setuptools.packages.find]
91
+ where = ["src"]
92
+
93
+ [tool.setuptools_scm]
94
+ # A release is a tag vX.Y.Z on master; between tags the version is X.Y.(Z+1).devN+g<sha>.
95
+ version_file = "src/agnimhd/_version.py"
96
+
97
+ [tool.setuptools.package-data]
98
+ agnimhd = ["py.typed"]
99
+
100
+ [tool.pytest.ini_options]
101
+ testpaths = ["tests"]
102
+ markers = [
103
+ "slow: takes more than ~60 s. NOT deselected in CI -- the four-way\n pytest-split matrix in ci.yml absorbs it. Deselecting would hide the\n solver tests, which are the slow ones and the ones worth running.",
104
+ "regression: pins a measured number from a documented run.",
105
+ ]
106
+ filterwarnings = ["error::DeprecationWarning:agnimhd.*"]
107
+
108
+ [tool.coverage.run]
109
+ # A PACKAGE name, not a file path. Handing coverage a .py path silently
110
+ # measures nothing and reports "No data to report".
111
+ source = ["agnimhd"]
112
+ branch = true
113
+
114
+ [tool.coverage.report]
115
+ exclude_lines = [
116
+ "pragma: no cover",
117
+ "raise NotImplementedError",
118
+ "if TYPE_CHECKING:",
119
+ ]
120
+
121
+ [tool.black]
122
+ line-length = 88
123
+ target-version = ["py310"]
124
+
125
+ [tool.isort]
126
+ profile = "black"
127
+ line_length = 88
128
+
129
+ [tool.flake8]
130
+ max-line-length = 88
131
+ extend-ignore = ["E203", "W503"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,52 @@
1
+ """AGNI -- Analysis of Global Normal-modes in Ideal MHD.
2
+
3
+ A differentiable finite-n ideal MHD stability solver.
4
+
5
+ AGNI solves ideal MHD stability from a **variational principle**: it discretizes
6
+ the energy functional rather than the force operator. That gives a generalized
7
+ symmetric eigenvalue problem ``A x = lambda B x`` with ``B`` (the kinetic/mass
8
+ matrix) symmetric positive definite. ``B`` is Cholesky-factored to reduce this to
9
+ a standard symmetric eigenvalue problem. Everything agnimhd returns is the
10
+ squared growth rate ``gamma^2 = -lambda`` of the most negative eigenvalue
11
+ ``lambda``: **positive means unstable**.
12
+
13
+ The package depends on ``jax``, ``numpy``, ``scipy`` and ``matfree``.
14
+ :func:`from_desc` imports DESC when it is called; nothing else does. Other
15
+ equilibrium codes fill an :class:`EquilibriumData` directly; see
16
+ ``docs/interface.md``.
17
+ """
18
+
19
+ from .adapters import from_desc
20
+ from .basis import Basis, DiffMat
21
+ from .config import AssemblyConfig, SolverConfig
22
+ from .equilibrium import FORMAT_VERSION, EquilibriumData
23
+ from .objective import (
24
+ eigenpair,
25
+ growth_rate,
26
+ growth_rate_and_grad,
27
+ growth_rate_of,
28
+ solve,
29
+ )
30
+ from .sources import load
31
+
32
+ __all__ = [
33
+ "AssemblyConfig",
34
+ "Basis",
35
+ "DiffMat",
36
+ "EquilibriumData",
37
+ "FORMAT_VERSION",
38
+ "SolverConfig",
39
+ "eigenpair",
40
+ "from_desc",
41
+ "growth_rate",
42
+ "growth_rate_and_grad",
43
+ "growth_rate_of",
44
+ "load",
45
+ "solve",
46
+ "__version__",
47
+ ]
48
+
49
+ try: # written by setuptools_scm at build or install time
50
+ from ._version import __version__
51
+ except ImportError: # a bare checkout on sys.path
52
+ __version__ = "0+unknown"
@@ -0,0 +1,24 @@
1
+ # file generated by vcs-versioning
2
+ # don't change, don't track in version control
3
+ from __future__ import annotations
4
+
5
+ __all__ = [
6
+ "__version__",
7
+ "__version_tuple__",
8
+ "version",
9
+ "version_tuple",
10
+ "__commit_id__",
11
+ "commit_id",
12
+ ]
13
+
14
+ version: str
15
+ __version__: str
16
+ __version_tuple__: tuple[int | str, ...]
17
+ version_tuple: tuple[int | str, ...]
18
+ commit_id: str | None
19
+ __commit_id__: str | None
20
+
21
+ __version__ = version = '0.1.0'
22
+ __version_tuple__ = version_tuple = (0, 1, 0)
23
+
24
+ __commit_id__ = commit_id = 'g4d8e50872'
@@ -0,0 +1,10 @@
1
+ """Adapters from equilibrium codes to :class:`agnimhd.EquilibriumData`.
2
+
3
+ Each adapter imports its equilibrium code lazily, inside the function, so the
4
+ package itself stays free of those dependencies: ``agnimhd`` installs and runs
5
+ without DESC; ``from_desc`` only works when DESC is importable.
6
+ """
7
+
8
+ from .desc import from_desc
9
+
10
+ __all__ = ["from_desc"]