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.
- agnimhd-0.1.0/.pymon +0 -0
- agnimhd-0.1.0/.zenodo.json +13 -0
- agnimhd-0.1.0/CITATION.cff +26 -0
- agnimhd-0.1.0/LICENSE +21 -0
- agnimhd-0.1.0/MANIFEST.in +12 -0
- agnimhd-0.1.0/PKG-INFO +148 -0
- agnimhd-0.1.0/README.md +97 -0
- agnimhd-0.1.0/pyproject.toml +131 -0
- agnimhd-0.1.0/setup.cfg +4 -0
- agnimhd-0.1.0/src/agnimhd/__init__.py +52 -0
- agnimhd-0.1.0/src/agnimhd/_version.py +24 -0
- agnimhd-0.1.0/src/agnimhd/adapters/__init__.py +10 -0
- agnimhd-0.1.0/src/agnimhd/adapters/desc.py +139 -0
- agnimhd-0.1.0/src/agnimhd/adapters/desc_objective.py +355 -0
- agnimhd-0.1.0/src/agnimhd/assemble.py +1212 -0
- agnimhd-0.1.0/src/agnimhd/backend.py +87 -0
- agnimhd-0.1.0/src/agnimhd/basis/__init__.py +43 -0
- agnimhd-0.1.0/src/agnimhd/basis/diffmat.py +957 -0
- agnimhd-0.1.0/src/agnimhd/basis/zernike.py +482 -0
- agnimhd-0.1.0/src/agnimhd/cli.py +257 -0
- agnimhd-0.1.0/src/agnimhd/config.py +302 -0
- agnimhd-0.1.0/src/agnimhd/equilibrium.py +724 -0
- agnimhd-0.1.0/src/agnimhd/multigpu.py +92 -0
- agnimhd-0.1.0/src/agnimhd/objective.py +912 -0
- agnimhd-0.1.0/src/agnimhd/plotting.py +474 -0
- agnimhd-0.1.0/src/agnimhd/py.typed +0 -0
- agnimhd-0.1.0/src/agnimhd/quadrature.py +284 -0
- agnimhd-0.1.0/src/agnimhd/solvers.py +857 -0
- agnimhd-0.1.0/src/agnimhd/sources.py +81 -0
- agnimhd-0.1.0/src/agnimhd/symmetry.py +119 -0
- agnimhd-0.1.0/src/agnimhd.egg-info/PKG-INFO +148 -0
- agnimhd-0.1.0/src/agnimhd.egg-info/SOURCES.txt +36 -0
- agnimhd-0.1.0/src/agnimhd.egg-info/dependency_links.txt +1 -0
- agnimhd-0.1.0/src/agnimhd.egg-info/entry_points.txt +2 -0
- agnimhd-0.1.0/src/agnimhd.egg-info/requires.txt +39 -0
- agnimhd-0.1.0/src/agnimhd.egg-info/scm_file_list.json +118 -0
- agnimhd-0.1.0/src/agnimhd.egg-info/scm_version.json +8 -0
- 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
|
+
[](https://github.com/rahulgaur104/AGNI/actions/workflows/ci.yml)
|
|
55
|
+
[](https://rahulgaur104.github.io/AGNI/)
|
|
56
|
+
[](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.
|
agnimhd-0.1.0/README.md
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# agnimhd
|
|
2
|
+
|
|
3
|
+
[](https://github.com/rahulgaur104/AGNI/actions/workflows/ci.yml)
|
|
4
|
+
[](https://rahulgaur104.github.io/AGNI/)
|
|
5
|
+
[](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"]
|
agnimhd-0.1.0/setup.cfg
ADDED
|
@@ -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"]
|