Skip to content

Commit e1607f2

Browse files
committed
Merge remote-tracking branch 'origin/main' into lao-betap-li-static-profile
# Conflicts: # examples/example09 - virtual_circuits_MASTU.ipynb # freegsnke/virtual_circuits.py
2 parents b5a6270 + 0ef7413 commit e1607f2

56 files changed

Lines changed: 12679 additions & 1678 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/docstrings.yml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
name: Docs Coverage Check
2+
3+
on:
4+
pull_request:
5+
branches:
6+
- main
7+
8+
jobs:
9+
docs-coverage:
10+
runs-on: ubuntu-latest
11+
steps:
12+
- name: Checkout
13+
uses: actions/checkout@v4
14+
- name: Setup
15+
uses: './.github/actions/cicd-setup'
16+
- name: Check docstring coverage
17+
run: interrogate --fail-under 95 freegsnke/

.github/workflows/notebooks.yml

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,24 @@ jobs:
2727
- name: Check static forward solve MAST-U notebook
2828
run: jupyter nbconvert --execute --to notebook --inplace "examples/example02 - static_forward_solve_MASTU.ipynb"
2929
- name: Check extracting equilibrium quantities notebook
30-
run: jupyter nbconvert --execute --to notebook --inplace "examples/example03 - extracting_equilibrium_quantites.ipynb"
30+
run: jupyter nbconvert --execute --to notebook --inplace "examples/example03 - extracting_equilibrium_quantities.ipynb"
3131
- name: Check using magnetic probes notebook
3232
run: jupyter nbconvert --execute --to notebook --inplace "examples/example04 - using_magnetic_probes.ipynb"
33-
- name: Check evolutive forward solve notebook
34-
run: jupyter nbconvert --execute --to notebook --inplace "examples/example05 - evolutive_forward_solve.ipynb"
33+
- name: Check evolutive forward solve notebook (5a)
34+
run: jupyter nbconvert --execute --to notebook --inplace "examples/example05a - nonlinear_and_linear_evolution_with_GS.ipynb"
35+
- name: Check evolutive forward solve notebook (5b)
36+
run: jupyter nbconvert --execute --to notebook --inplace "examples/example05b - linear_evolution_without_GS.ipynb"
37+
- name: Check evolutive forward solve notebook (5c)
38+
run: jupyter nbconvert --execute --to notebook --inplace "examples/example05c - linear_evolution_with_relinearisation.ipynb"
39+
- name: Check static inverse solve Anamak notebook
40+
run: jupyter nbconvert --execute --to notebook --inplace "examples/example07a - Anamak"
3541
- name: Check static inverse solve SPARC notebook
36-
run: jupyter nbconvert --execute --to notebook --inplace "examples/example07 - static_inverse_solve_SPARC.ipynb"
42+
run: jupyter nbconvert --execute --to notebook --inplace "examples/example07b - SPARC"
43+
- name: Check static inverse solve ITER notebook
44+
run: jupyter nbconvert --execute --to notebook --inplace "examples/example07c - ITER"
3745
- name: Check virtual circuits MAST-U notebook
3846
run: jupyter nbconvert --execute --to notebook --inplace "examples/example09 - virtual_circuits_MASTU.ipynb"
3947
- name: Check growth rates notebook
40-
run: jupyter nbconvert --execute --to notebook --inplace "examples/example10 - growth_rates.ipynb"
48+
run: jupyter nbconvert --execute --to notebook --inplace "examples/example10 - growth_rates.ipynb"
49+
- name: Check pulse design tool notebook
50+
run: jupyter nbconvert --execute --to notebook --inplace "examples/example11 - pulse_design_tool.ipynb"

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,5 +52,7 @@ build/
5252
examples/.virtual_documents/*
5353
.virtual_documents/
5454
.netlify
55+
examples/control_pickles/*
56+
freegsnke/control_loop/control_test_files/*
5557
.github/copilot-instructions.md
56-
AGENTS.md
58+
AGENTS.md

README.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,27 @@ Static Grad-Shafranov problems are solved using **fourth-order accurate finite d
4040

4141
In the left panel above we show an example of a dynamic equilibrium calculated using FreeGSNKE's forward solver, simulating the flat-phase of a **MAST-U** plasma discharge. On the right is the sequence of EFIT equilibrium reconstructions from the actual MAST-U shot (re-plotted using FreeGSNKE). We can see clear agreement between the simulation and the reconstructions in both the plasma shape and the currents in the poloidal field coils, illustrating FreeGSNKE's accuracy. The contours represent constant poloidal flux and the different tokamak features are plotted in various colours (refer back to table above - noting magnetic probes not shown here).
4242

43+
## Coordinate and flux conventions
44+
45+
FreeGSNKE inherits its magnetic sign and flux conventions from FreeGS4E. Internally, the poloidal flux function `psi` is stored in Webers per radian (`Wb/rad`, equivalently `Webers/2pi`) and the Grad-Shafranov operator is written as:
46+
47+
```text
48+
Delta* psi = - mu0 R J_phi
49+
```
50+
51+
The poloidal magnetic field components are obtained from:
52+
53+
```text
54+
B_R = -(1/R) dpsi/dZ
55+
B_Z = (1/R) dpsi/dR
56+
```
57+
58+
or, equivalently, `B_p = grad(psi) x grad(phi)` in the usual right-handed cylindrical coordinate system `(R, phi, Z)`. The toroidal field function is `F = R B_phi`, and the plasma current `Ip` is the integral of `J_phi` over the poloidal cross-section.
59+
60+
Using the Sauter-Medvedev COCOS sign flags, these internal equations correspond to a **COCOS-7-like convention**: `exp_Bp = 0`, `sigma_Bp = -1`, `sigma_RpZ = +1`, and `sigma_rhotp = +1`.
61+
62+
The low-level `cocos` argument in the current FreeGS4E G-EQDSK parser is only a partial conversion helper: `cocos < 10` leaves `psi` in `Wb/rad`, while `cocos > 10` divides `psi`, `simagx`, and `sibdry` by `2pi`. It does not apply the full set of sign changes required to transform arbitrary COCOS conventions. In practical terms, when importing or exporting equilibria from external tools, check both the `2pi` flux scaling and the signs of `psi`, `Ip`, `B_phi`, `F`, and `q`. The higher-level FreeGS4E equilibrium import path should also be validated for your use case before relying on it in production workflows.
63+
4364
## Feature roadmap
4465
FreeGSNKE is constantly evolving and so we hope to provide users with more advanced features over time:
4566

docs/build_documentation.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ cp "../examples/example00 - build_tokamak_machine.ipynb" notebooks
88
cp "../examples/example01a - static_inverse_solve_MASTU.ipynb" notebooks
99
cp "../examples/example01b - advanced_static_inverse_solve.ipynb" notebooks
1010
cp "../examples/example02 - static_forward_solve_MASTU.ipynb" notebooks
11-
cp "../examples/example03 - extracting_equilibrium_quantites.ipynb" notebooks
11+
cp "../examples/example03 - extracting_equilibrium_quantities.ipynb" notebooks
1212
cp "../examples/example04 - using_magnetic_probes.ipynb" notebooks
1313
cp "../examples/example05 - evolutive_forward_solve.ipynb" notebooks
1414
cp "../examples/example07 - static_inverse_solve_SPARC.ipynb" notebooks

docs/user_guide/index.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ The notebooks are displayed statically on the following pages, but running them
1515
../notebooks/example01a - static_inverse_solve_MASTU
1616
../notebooks/example01b - advanced_static_inverse_solve
1717
../notebooks/example02 - static_forward_solve_MASTU
18-
../notebooks/example03 - extracting_equilibrium_quantites
18+
../notebooks/example03 - extracting_equilibrium_quantities
1919
../notebooks/example04 - using_magnetic_probes
2020
../notebooks/example05 - evolutive_forward_solve
2121
../notebooks/example07 - static_inverse_solve_SPARC

examples/README.md

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,24 @@
11
# Examples
22

3-
These example Jupyter notebooks are intended to be the **first port of call for new users** trying to get up to speed with the basics of simulating Grad-Shafranov equilibria using FreeGSNKE (the numberings represent approximately increasing complexity!). Most examples will use a MAST-U-like tokamak machine, unless otherwise specified.
3+
These example Jupyter notebooks are intended to be the **first port of call for new users** trying to get up to speed with the basics of simulating Grad-Shafranov equilibria using FreeGSNKE (the numbering represents approximately increasing complexity!). Most examples will use a MAST-U-like tokamak machine, unless otherwise specified.
44

55
| Example notebook | Purpose | Who can use it? |
6-
| ------ | ------ | ------ |
6+
| ------ | ------ | ------ |
77
| Example 00 | Learn how to build a generic tokamak object. | Anyone |
88
| Example 01a | Learn how to use the static inverse solver. | Anyone |
9-
| Example 01b | Learn how to use more advacned features of the static inverse solver. | Anyone |
9+
| Example 01b | Learn how to use more advanced features of the static inverse solver. | Anyone |
1010
| Example 02 | Learn how to use the static forward solver. | Anyone |
1111
| Example 03 | Learn how to extract results from a calculated equilibrium. | Anyone |
1212
| Example 04 | Learn how to use the magnetic probes object. | Anyone |
13-
| Example 05 | Learn how to use the evolutive solver to simulate time-dependent equilibria. | Anyone |
13+
| Example 05a | Learn how to use the nonlinear and linear (with GS) evolutive solver to simulate time-dependent equilibria. | Anyone |
14+
| Example 05b | Learn how to use the linear evolutive solver without solving GS at each timestep. | Anyone |
15+
| Example 05c | Learn how to use the linear evolutive solver (with or without solving GS) with automatic relinearisation enabled. | Anyone |
1416
| Example 06a/b | Simulate (static) MAST-U equilibria over an entire shot using inputs from EFIT++ (requires internal UKAEA MAST-U database). | UKAEA employees + collaborators |
15-
| Example 07 | Static inverse solve in a SPARC-like tokamak. | Anyone |
16-
| Example 08 | Static inverse solve in an ITER-like tokamak. | Anyone |
17+
| Example 07a | Static inverse solve in the "Anamak" toy tokamak. | Anyone |
18+
| Example 07b | Static inverse solve in a SPARC-like tokamak. | Anyone |
19+
| Example 07c | Static inverse solve in an ITER-like tokamak. | Anyone |
1720
| Example 09 | Learn how to use and build virtual circuits for plasma shape control. | Anyone |
1821
| Example 10 | Learn how to calculate growth rates associated with vertically unstable modes. | Anyone |
22+
| Example 11 | Learn how to use the evolutive solver alongside a virtual plasma control system (FreeGSNKE Pulse Design Tool). | Anyone |
1923

2024
If a new example has been created, please add a new line to the table explaining its purpose!

examples/example00 - build_tokamak_machine.ipynb

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"source": [
77
"# Example: Machine configuration\n",
88
"\n",
9-
"Here we will describe how to create the machine description files required to begin solving for Grad-Shafranov equilbiria in FreeGSNKE. \n",
9+
"Here we will describe how to create the machine description files required to begin solving for Grad-Shafranov equilibria in FreeGSNKE. \n",
1010
"\n",
1111
"A machine description in FreeGSNKE is comprised of:\n",
1212
"- **active coils** : whose currents and voltages are used to control the plasma shape and position.\n",
@@ -77,7 +77,7 @@
7777
"- `polarity`: circuit wiring, enabling coil pairs to be linked in series or anti-series (typically +1 or -1).\n",
7878
"- `multiplier`: current multiplier, used for splitting current among coils (default = 1).\n",
7979
"\n",
80-
"First, instatiate the dictionary that will contain all of the coils:"
80+
"First, instantiate the dictionary that will contain all of the coils:"
8181
]
8282
},
8383
{
@@ -93,7 +93,7 @@
9393
"cell_type": "markdown",
9494
"metadata": {},
9595
"source": [
96-
"Let's define the standalone `Pz` coil first."
96+
"Let's define the standalone `Pz` coil first."
9797
]
9898
},
9999
{
@@ -240,7 +240,7 @@
240240
"## Passive structures\n",
241241
"Passive structures in FreeGSNKE are toroidally symmetric conducting structures that contain eddy currents induced by the active coils and the plasma. These non-voltage driven currents alter the magnetic field in the device and significantly affect equilibrium calculations. These can include support structures, the vessel, coil cans, etc.\n",
242242
"\n",
243-
"FreeGSNKE supports two different kind of passive structures:\n",
243+
"FreeGSNKE supports two different kinds of passive structures:\n",
244244
"- filaments (i.e. single point sources)\n",
245245
"- polygonal structures (i.e. multiple grouped filaments). \n",
246246
"\n",
@@ -455,7 +455,7 @@
455455
"source": [
456456
"## Magnetic Probes \n",
457457
"\n",
458-
"There are a variety of magnetic probes in the machine that measure various components of the magnetic field and or the flux function. The description of these is contained in a dictionary we'll call `magnetic_probes` which has the probe type as a key and then a list of smaller dictionaries for each individual probe. Currently the *flux loops* and *pickup coils* are implemented (others may be implemented at a later date).\n",
458+
"There are a variety of magnetic probes in the machine that measure various components of the magnetic field and/or the flux function. The description of these is contained in a dictionary we'll call `magnetic_probes` which has the probe type as a key and then a list of smaller dictionaries for each individual probe. Currently the *flux loops* and *pickup coils* are implemented (others may be implemented at a later date).\n",
459459
"- The **flux loops** compute the flux function $\\psi(R,Z)$. The dictionary description contains the `name` and the `position` of the probe which is a 2D array with $R$ and $Z$ coordinates. \n",
460460
"- The **pickup coils** compute $B\\cdot \\hat n$ where $\\hat n$ is a unit orientation vector of the probe. They are described by dictionaries containing the `name` as before, the `position` which is now a 3D array of coordinates $(R,\\phi,Z)$, an `orientation` key with a string description of the orientation (parallel, toroidal, normal), and finally an `orientation_vector` $\\hat n$. This is also a 3D array - it must be the same dimension as the position. \n",
461461
"\n",
@@ -509,7 +509,7 @@
509509
"cell_type": "markdown",
510510
"metadata": {},
511511
"source": [
512-
"First, we set the paths to the pickle files we've just built. Then when we call 'build_machine.tokamak()', it will know which files to use. After this, we can plot the machine directly from the tokamak object (note that the limiter and wall need to be plot separately). "
512+
"First, we set the paths to the pickle files we've just built. Then when we call 'build_machine.tokamak()', it will know which files to use. After this, we can plot the machine directly from the tokamak object (note that the limiter and wall need to be plotted separately). "
513513
]
514514
},
515515
{
@@ -542,7 +542,7 @@
542542
"metadata": {},
543543
"outputs": [],
544544
"source": [
545-
"# plot the resulting equilbria \n",
545+
"# plot the resulting equilibria \n",
546546
"fig1, ax1 = plt.subplots(1, 1, figsize=(4, 8), dpi=80)\n",
547547
"plt.tight_layout()\n",
548548
"\n",
@@ -562,7 +562,7 @@
562562
"cell_type": "markdown",
563563
"metadata": {},
564564
"source": [
565-
"It is worth spending some time exploring the `tokamak` object to get familiar with all of the information it holds. A number of methods may not work properly yet as we have not instatiated an equilibrium object (that will be in a future notebook). \n",
565+
"It is worth spending some time exploring the `tokamak` object to get familiar with all of the information it holds. A number of methods may not work properly yet as we have not instantiated an equilibrium object (that will be in a future notebook).\n",
566566
"\n",
567567
"We can, however, look at the active coils and other features defined in our tokamak."
568568
]
@@ -684,7 +684,7 @@
684684
"metadata": {},
685685
"outputs": [],
686686
"source": [
687-
"# plot the resulting equilbria \n",
687+
"# plot the resulting equilibria \n",
688688
"fig1, ax1 = plt.subplots(1, 1, figsize=(4, 8), dpi=80)\n",
689689
"plt.tight_layout()\n",
690690
"\n",

0 commit comments

Comments
 (0)