Grad-Shafranov¶
These helpers provide the axisymmetric finite-difference flux solve path.
Key preconditions:
flux_solver()andsolve_flux_axisymmetric()require strictly increasing, regularrandzgrids withr > 0and at least 7 points on each axis.solve_flux_axisymmetric()expectsmeshes = np.meshgrid(*grids, indexing="ij")andcurrent_densityon the same(nr, nz)layout, with zero current on the finite-difference boundary.gradient_order4()andcalc_flux_density_from_flux()require at least 6 points on each axis, andcalc_flux_density_from_flux()also requiresrmesh > 0.
cfsem.gs_operator_order2 ¶
Build second-order Grad-Shafranov operator in triplet format. Assumes regular grid spacing.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
rs
|
NDArray[float64]
|
[m] r-coordinates of finite difference grid |
required |
zs
|
NDArray[float64]
|
[m] z-coordinates of finite difference grid |
required |
Returns:
| Type | Description |
|---|---|
Array3xN
|
Differential operator as triplet format sparse matrix |
Source code in cfsem/bindings.py
cfsem.gs_operator_order4 ¶
Build fourth-order Grad-Shafranov operator in triplet format. Assumes regular grid spacing.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
rs
|
NDArray[float64]
|
[m] r-coordinates of finite difference grid |
required |
zs
|
NDArray[float64]
|
[m] z-coordinates of finite difference grid |
required |
Returns:
| Type | Description |
|---|---|
Array3xN
|
Differential operator as triplet format sparse matrix |
Source code in cfsem/bindings.py
cfsem.gradient_order4 ¶
Calculate gradient by 4th-order finite difference.
numpy.gradient exists and is fast and convenient, but only uses a second-order difference,
which produces unacceptable error in B-fields (well over 1% for typical geometries).
Errors¶
* If the input grids are not regular
* If any input grid dimensions have size less than 6
References¶
* [1] “Finite difference coefficient,” Wikipedia. Aug. 22, 2023.
Accessed: Mar. 29, 2024. [Online].
Available: https://en.wikipedia.org/w/index.php?title=Finite_difference_coefficient
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
z
|
NDArray
|
[ |
required |
xmesh
|
NDArray
|
[m] 2D array of coordinates of first dimension |
required |
ymesh
|
NDArray
|
[m] 2D array of coordinates of second dimension |
required |
Returns:
| Type | Description |
|---|---|
tuple[NDArray, NDArray]
|
(dzdx, dzdy) [ |
Source code in cfsem/flux_solver.py
cfsem.calc_flux_density_from_flux ¶
calc_flux_density_from_flux(
psi: NDArray, rmesh: NDArray, zmesh: NDArray
) -> tuple[NDArray, NDArray]
Back-calculate B-field from poloidal flux per Wesson eqn 3.2.2 by 4th-order finite difference, modified to use total poloidal flux instead of flux per radian.
This avoids an expensive sum over filamentized contributions at the expense of some numerical error.
Errors¶
* If the input grids are not regular
* If any input grid dimensions have size less than 6
* If `rmesh` contains non-positive radii
References¶
* [1] J. Wesson, Tokamaks. Oxford, New York: Clarendon Press, 1987.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
psi
|
NDArray
|
[Wb] poloidal flux |
required |
rmesh
|
NDArray
|
[m] 2D r-coordinates |
required |
zmesh
|
NDArray
|
[m] 2D z-coordinates |
required |
Returns:
| Type | Description |
|---|---|
tuple[NDArray, NDArray]
|
(br, bz) [T] 2D arrays of poloidal flux density |
Source code in cfsem/flux_solver.py
cfsem.flux_solver ¶
Axisymmetric finite-difference flux solve helpers.
calc_flux_density_from_flux ¶
calc_flux_density_from_flux(
psi: NDArray, rmesh: NDArray, zmesh: NDArray
) -> tuple[NDArray, NDArray]
Back-calculate B-field from poloidal flux per Wesson eqn 3.2.2 by 4th-order finite difference, modified to use total poloidal flux instead of flux per radian.
This avoids an expensive sum over filamentized contributions at the expense of some numerical error.
Errors¶
* If the input grids are not regular
* If any input grid dimensions have size less than 6
* If `rmesh` contains non-positive radii
References¶
* [1] J. Wesson, Tokamaks. Oxford, New York: Clarendon Press, 1987.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
psi
|
NDArray
|
[Wb] poloidal flux |
required |
rmesh
|
NDArray
|
[m] 2D r-coordinates |
required |
zmesh
|
NDArray
|
[m] 2D z-coordinates |
required |
Returns:
| Type | Description |
|---|---|
tuple[NDArray, NDArray]
|
(br, bz) [T] 2D arrays of poloidal flux density |
Source code in cfsem/flux_solver.py
flux_solver ¶
Linear solver for extracting a flux field from a toroidal current density distribution
using a 4th-order finite difference approximation of the Grad-Shafranov PDE.
For jtor toroidal current density shaped like (nr, nz), call like psi = flux_solver(rhs)
to get psi in [Wb] or [V-s], where rhs = -2.0 * np.pi * mu_0 * rmesh * jtor with the boundary
values set to the circular-filament solved flux.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
grids
|
tuple[NDArray, NDArray]
|
[m] regular 1D r,z grids. The fourth-order Grad-Shafranov stencil requires strictly increasing grids with positive radius and at least 7 points on each axis. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
solver |
Callable[[NDArray], NDArray]
|
factorized solver for Grad-Shafranov differential operator |
Source code in cfsem/flux_solver.py
gradient_order4 ¶
Calculate gradient by 4th-order finite difference.
numpy.gradient exists and is fast and convenient, but only uses a second-order difference,
which produces unacceptable error in B-fields (well over 1% for typical geometries).
Errors¶
* If the input grids are not regular
* If any input grid dimensions have size less than 6
References¶
* [1] “Finite difference coefficient,” Wikipedia. Aug. 22, 2023.
Accessed: Mar. 29, 2024. [Online].
Available: https://en.wikipedia.org/w/index.php?title=Finite_difference_coefficient
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
z
|
NDArray
|
[ |
required |
xmesh
|
NDArray
|
[m] 2D array of coordinates of first dimension |
required |
ymesh
|
NDArray
|
[m] 2D array of coordinates of second dimension |
required |
Returns:
| Type | Description |
|---|---|
tuple[NDArray, NDArray]
|
(dzdx, dzdy) [ |
Source code in cfsem/flux_solver.py
solve_flux_axisymmetric ¶
solve_flux_axisymmetric(
grids: tuple[NDArray, NDArray],
meshes: tuple[NDArray, NDArray],
current_density: NDArray,
solver: Callable[[NDArray], NDArray] | None = None,
) -> NDArray
Calculate the flux field associated with a given toroidal current density distribution, by solving the Grad-Shafranov PDE.
This calculation is most commonly used for the plasma, but is in fact more general, and applies to anything with an equivalent toroidal current density and axisymmetry.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
grids
|
tuple[NDArray, NDArray]
|
[m] 1D r,z regular coordinate grids. The fourth-order solve requires strictly increasing grids with positive radius and at least 7 points on each axis. |
required |
meshes
|
tuple[NDArray, NDArray]
|
[m] 2D meshgrids made from grids like np.meshgrid(*grids, indexing="ij") |
required |
current_density
|
NDArray
|
[A/m^2], shape (nr, nz), toroidal current density on finite-difference mesh with zero values on the finite-difference boundary |
required |
solver
|
Callable[[NDArray], NDArray] | None
|
Optionally, provide a pre-initialized linear solver. See |
None
|
Returns:
| Type | Description |
|---|---|
NDArray
|
poloidal flux field, [Wb] with shape (nr, nz) |
Source code in cfsem/flux_solver.py
cfsem.solve_flux_axisymmetric ¶
solve_flux_axisymmetric(
grids: tuple[NDArray, NDArray],
meshes: tuple[NDArray, NDArray],
current_density: NDArray,
solver: Callable[[NDArray], NDArray] | None = None,
) -> NDArray
Calculate the flux field associated with a given toroidal current density distribution, by solving the Grad-Shafranov PDE.
This calculation is most commonly used for the plasma, but is in fact more general, and applies to anything with an equivalent toroidal current density and axisymmetry.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
grids
|
tuple[NDArray, NDArray]
|
[m] 1D r,z regular coordinate grids. The fourth-order solve requires strictly increasing grids with positive radius and at least 7 points on each axis. |
required |
meshes
|
tuple[NDArray, NDArray]
|
[m] 2D meshgrids made from grids like np.meshgrid(*grids, indexing="ij") |
required |
current_density
|
NDArray
|
[A/m^2], shape (nr, nz), toroidal current density on finite-difference mesh with zero values on the finite-difference boundary |
required |
solver
|
Callable[[NDArray], NDArray] | None
|
Optionally, provide a pre-initialized linear solver. See |
None
|
Returns:
| Type | Description |
|---|---|
NDArray
|
poloidal flux field, [Wb] with shape (nr, nz) |