Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fourier bounce #1119

Open
wants to merge 64 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
d5b231e
Merge branch 'master' into ku/fourier_bounce
unalmis Aug 27, 2024
8d8aa78
MANUAL Merge branch 'bounce' into ku/fourier_bounce
unalmis Aug 28, 2024
a0e31ce
Fix missed things with manual merge in commit 8d8aa78
unalmis Aug 28, 2024
4d469e8
Merge branch 'master' into ku/fourier_bounce
unalmis Sep 16, 2024
dbd80a5
Reviving fourier bounce pull request
unalmis Sep 17, 2024
29fa913
Progressing
unalmis Sep 18, 2024
fa12723
Isolated issue of fourier series convergence to modding of theta by 2pi
unalmis Sep 18, 2024
5d93b3c
Merge branch 'master' into ku/fourier_bounce
unalmis Sep 18, 2024
e4f68b7
Update desc_from_clebsch function
unalmis Sep 18, 2024
fe60029
Merge branch 'master' into ku/fourier_bounce
unalmis Sep 18, 2024
a1fad7e
Merge branch 'ku/stop_angle_mod' into ku/fourier_bounce
unalmis Sep 19, 2024
7113d3f
Debugging cusp
unalmis Sep 19, 2024
0b14c20
document something that should be testd more
unalmis Sep 19, 2024
6c14202
Note that more poloidal resolution is needed
unalmis Sep 19, 2024
be0aa6b
Merge branch 'master' into ku/fourier_bounce
unalmis Sep 19, 2024
c348378
fix test
unalmis Sep 19, 2024
258dad0
-----
unalmis Sep 19, 2024
22df224
Document solution to discontinuity
unalmis Sep 19, 2024
2781681
Fix comment
unalmis Sep 19, 2024
41d440a
Remove unnecessary interpolation:
unalmis Sep 21, 2024
a5c87a4
Doing stuff marked todo
unalmis Sep 21, 2024
4eb6db2
testing
unalmis Sep 21, 2024
87dc90d
Improving API to avoid redundant computation
unalmis Sep 22, 2024
142c13c
Merge branch 'ku/fourier_bounce_part1' into ku/fourier_bounce
unalmis Sep 22, 2024
1d5a84d
Merge branch 'ku/fourier_bounce_part1' into ku/fourier_bounce
unalmis Sep 22, 2024
7977695
Document choice for quadrature
unalmis Sep 22, 2024
fe3d7b4
Merge branch 'ku/fourier_bounce_part1' into ku/fourier_bounce
unalmis Sep 22, 2024
53ca834
More documentation
unalmis Sep 22, 2024
679697f
Document multivaluedness bug and how to fix. likely will be done in n…
unalmis Sep 24, 2024
dfb3eee
Merge branch 'ku/fourier_bounce_part1' into ku/fourier_bounce
unalmis Sep 24, 2024
b270de8
Merge branch 'master' into ku/fourier_bounce
unalmis Sep 24, 2024
38e71e9
Marking test xfail
unalmis Sep 25, 2024
05cb195
Adding more tests and documentation
unalmis Sep 25, 2024
ff2d204
Merge branch 'master' into ku/fourier_bounce
unalmis Sep 26, 2024
134d826
short-circuit convergence of poloidal Fourier series
unalmis Sep 26, 2024
455353f
Remove resolved comment
unalmis Sep 26, 2024
f63f3b3
Stitch theta as well for robustness
unalmis Sep 26, 2024
19e6bd1
Merge branch 'master' into ku/fourier_bounce
unalmis Sep 27, 2024
b1de0d6
Solved the convergence issue
unalmis Sep 27, 2024
e028106
support vector valued to simplify multivalued function reconstruction
unalmis Sep 27, 2024
2ce57ee
Fix comment
unalmis Sep 27, 2024
32fcdb2
Merge branch 'master' into ku/fourier_bounce
unalmis Sep 29, 2024
7b1267a
Add explanation of math in c
unalmis Sep 29, 2024
47988d1
small but important typo in comment
unalmis Sep 29, 2024
f78d7bd
Merge branch 'master' into ku/fourier_bounce
unalmis Sep 30, 2024
ea227a1
Genealize to NFP!=1
unalmis Oct 2, 2024
18af538
Merge branch 'master' into ku/fourier_bounce
unalmis Oct 2, 2024
89762c7
Add NFP to get_rtz_grid
unalmis Oct 2, 2024
c3e465b
More NFP fixes
unalmis Oct 2, 2024
3871353
Got things working now
unalmis Oct 3, 2024
a5cf4bc
Merge branch 'master' into ku/fourier_bounce
unalmis Oct 3, 2024
60fc00f
Change NFP mismatch error back to warning
unalmis Oct 3, 2024
08b54af
Merge branch 'master' into ku/fourier_bounce
unalmis Oct 6, 2024
56dcbb2
Split compute quantities into periodic and secular terms
unalmis Oct 6, 2024
30d511e
Add ability to compute length along field line with fft
unalmis Oct 6, 2024
6870bcd
Make sure returned shape doesn't have extra dimension
unalmis Oct 6, 2024
5e72593
PUlling changes from downstream branch
unalmis Oct 6, 2024
ce64c53
Add missing key to stability fun test
unalmis Oct 6, 2024
7c88211
Document algorithm choices
unalmis Oct 6, 2024
1376e90
Update incorrect comment
unalmis Oct 6, 2024
d54a809
document better root finding method for later
unalmis Oct 7, 2024
8cef6d3
update ballooning notebook by explicitly comping gbdrift
unalmis Oct 7, 2024
0e07215
resolving jit error
unalmis Oct 7, 2024
47962de
Merge branch 'master' into ku/fourier_bounce
YigitElma Oct 12, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 47 additions & 3 deletions desc/compute/_basis_vectors.py
Original file line number Diff line number Diff line change
Expand Up @@ -3223,17 +3223,61 @@ def _e_sub_zeta_zz(params, transforms, profiles, data, **kwargs):
transforms={},
profiles=[],
coordinates="rtz",
data=["e^rho", "e^theta", "e^zeta", "alpha_r", "alpha_t", "alpha_z"],
data=["periodic(grad(alpha))", "secular(grad(alpha))"],
)
def _grad_alpha(params, transforms, profiles, data, **kwargs):
data["grad(alpha)"] = (
data["alpha_r"] * data["e^rho"].T
data["grad(alpha)"] = data["periodic(grad(alpha))"] + data["secular(grad(alpha))"]
return data


@register_compute_fun(
name="periodic(grad(alpha))",
label="\\mathrm{periodic}(\\nabla \\alpha)",
units="m^{-1}",
units_long="Inverse meters",
description=(
"Gradient of field line label, which is perpendicular to the field line, "
"periodic component"
),
dim=3,
params=[],
transforms={},
profiles=[],
coordinates="rtz",
data=["e^rho", "e^theta", "e^zeta", "periodic(alpha_r)", "alpha_t", "alpha_z"],
)
def _periodic_grad_alpha(params, transforms, profiles, data, **kwargs):
data["periodic(grad(alpha))"] = (
data["periodic(alpha_r)"] * data["e^rho"].T
+ data["alpha_t"] * data["e^theta"].T
+ data["alpha_z"] * data["e^zeta"].T
).T
return data


@register_compute_fun(
name="secular(grad(alpha))",
label="\\mathrm{secular}(\\nabla \\alpha)",
units="m^{-1}",
units_long="Inverse meters",
description=(
"Gradient of field line label, which is perpendicular to the field line, "
"periodic component"
),
dim=3,
params=[],
transforms={},
profiles=[],
coordinates="rtz",
data=["e^rho", "secular(alpha_r)"],
)
def _secular_grad_alpha(params, transforms, profiles, data, **kwargs):
data["secular(grad(alpha))"] = (
data["secular(alpha_r)"][:, jnp.newaxis] * data["e^rho"]
)
return data


@register_compute_fun(
name="grad(psi)",
label="\\nabla\\psi",
Expand Down
46 changes: 40 additions & 6 deletions desc/compute/_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -1518,14 +1518,48 @@ def _alpha(params, transforms, profiles, data, **kwargs):
transforms={},
profiles=[],
coordinates="rtz",
data=["theta_PEST_r", "phi", "phi_r", "iota", "iota_r"],
data=["periodic(alpha_r)", "secular(alpha_r)"],
)
def _alpha_r(params, transforms, profiles, data, **kwargs):
data["alpha_r"] = (
data["theta_PEST_r"]
- data["iota_r"] * data["phi"]
- data["iota"] * data["phi_r"]
)
data["alpha_r"] = data["periodic(alpha_r)"] + data["secular(alpha_r)"]
return data


@register_compute_fun(
name="periodic(alpha_r)",
label="\\mathrm{periodic}(\\partial_\\rho \\alpha)",
units="~",
units_long="None",
description="Field line label, derivative wrt radial coordinate, "
"periodic component",
dim=1,
params=[],
transforms={},
profiles=[],
coordinates="rtz",
data=["theta_PEST_r", "iota", "phi_r"],
)
def _periodic_alpha_r(params, transforms, profiles, data, **kwargs):
data["periodic(alpha_r)"] = data["theta_PEST_r"] - data["iota"] * data["phi_r"]
return data


@register_compute_fun(
name="secular(alpha_r)",
label="\\mathrm{secular}(\\partial_\\rho \\alpha)",
units="~",
units_long="None",
description="Field line label, derivative wrt radial coordinate, "
"secular component",
dim=1,
params=[],
transforms={},
profiles=[],
coordinates="rtz",
data=["iota_r", "phi"],
)
def _secular_alpha_r(params, transforms, profiles, data, **kwargs):
data["secular(alpha_r)"] = -data["iota_r"] * data["phi"]
return data


Expand Down
90 changes: 81 additions & 9 deletions desc/compute/_metric.py
Original file line number Diff line number Diff line change
Expand Up @@ -1941,8 +1941,8 @@ def _g_sup_ra(params, transforms, profiles, data, **kwargs):
# Exact definition of the magnetic drifts taken from
# eqn. 48 of Introduction to Quasisymmetry by Landreman
# https://tinyurl.com/54udvaa4
label="\\mathrm{gbdrift} = 1/B^{2} (\\mathbf{b}\\times\\nabla B) \\cdot"
+ "\\nabla \\alpha",
label="(\\nabla \\vert B \\vert)_{\\mathrm{drift}} = "
"(\\mathbf{b} \\times \\nabla B) \\cdot \\nabla \\alpha / \\vert B \\vert^{2}",
units="1/(T-m^{2})",
units_long="inverse Tesla meters^2",
description="Binormal component of the geometric part of the gradB drift"
Expand All @@ -1952,13 +1952,61 @@ def _g_sup_ra(params, transforms, profiles, data, **kwargs):
transforms={},
profiles=[],
coordinates="rtz",
data=["|B|^2", "b", "grad(alpha)", "grad(|B|)"],
data=["periodic(gbdrift)", "secular(gbdrift)"],
)
def _gbdrift(params, transforms, profiles, data, **kwargs):
data["gbdrift"] = (
1
data["gbdrift"] = data["periodic(gbdrift)"] + data["secular(gbdrift)"]
return data


@register_compute_fun(
name="periodic(gbdrift)",
# Exact definition of the magnetic drifts taken from
# eqn. 48 of Introduction to Quasisymmetry by Landreman
# https://tinyurl.com/54udvaa4
label="\\mathrm{periodic}(\\nabla \\vert B \\vert)_{\\mathrm{drift}}",
units="1/(T-m^{2})",
units_long="inverse Tesla meters^2",
description="Binormal component of the geometric part of the gradB drift"
+ " used for local stability analyses, Gamma_c, epsilon_eff etc."
" Periodic component.",
dim=1,
params=[],
transforms={},
profiles=[],
coordinates="rtz",
data=["|B|^2", "b", "periodic(grad(alpha))", "grad(|B|)"],
)
def _periodic_gbdrift(params, transforms, profiles, data, **kwargs):
data["periodic(gbdrift)"] = (
dot(data["b"], cross(data["grad(|B|)"], data["periodic(grad(alpha))"]))
/ data["|B|^2"]
)
return data


@register_compute_fun(
name="secular(gbdrift)",
# Exact definition of the magnetic drifts taken from
# eqn. 48 of Introduction to Quasisymmetry by Landreman
# https://tinyurl.com/54udvaa4
label="\\mathrm{secular}(\\nabla \\vert B \\vert)_{\\mathrm{drift}}",
units="1/(T-m^{2})",
units_long="inverse Tesla meters^2",
description="Binormal component of the geometric part of the gradB drift"
+ " used for local stability analyses, Gamma_c, epsilon_eff etc. "
"Secular component.",
dim=1,
params=[],
transforms={},
profiles=[],
coordinates="rtz",
data=["|B|^2", "b", "secular(grad(alpha))", "grad(|B|)"],
)
def _secular_gbdrift(params, transforms, profiles, data, **kwargs):
data["secular(gbdrift)"] = (
dot(data["b"], cross(data["grad(|B|)"], data["secular(grad(alpha))"]))
/ data["|B|^2"]
* dot(data["b"], cross(data["grad(|B|)"], data["grad(alpha)"]))
)
return data

Expand All @@ -1979,11 +2027,35 @@ def _gbdrift(params, transforms, profiles, data, **kwargs):
transforms={},
profiles=[],
coordinates="rtz",
data=["p_r", "psi_r", "|B|^2", "gbdrift"],
data=["periodic(cvdrift)", "secular(gbdrift)"],
)
def _cvdrift(params, transforms, profiles, data, **kwargs):
dp_dpsi = mu_0 * data["p_r"] / data["psi_r"]
data["cvdrift"] = 1 / data["|B|^2"] * dp_dpsi + data["gbdrift"]
data["cvdrift"] = data["periodic(cvdrift)"] + data["secular(gbdrift)"]
return data


@register_compute_fun(
name="periodic(cvdrift)",
# Exact definition of the magnetic drifts taken from
# eqn. 48 of Introduction to Quasisymmetry by Landreman
# https://tinyurl.com/54udvaa4
label="\\mathrm{periodic(cvdrift)}",
units="1/(T-m^{2})",
units_long="inverse Tesla meters^2",
description="Binormal component of the geometric part of the curvature drift"
+ " used for local stability analyses, Gamma_c, epsilon_eff etc. "
"Periodic component.",
dim=1,
params=[],
transforms={},
profiles=[],
coordinates="rtz",
data=["p_r", "psi_r", "|B|^2", "periodic(gbdrift)"],
)
def _periodic_cvdrift(params, transforms, profiles, data, **kwargs):
data["periodic(cvdrift)"] = (
mu_0 * data["p_r"] / data["psi_r"] / data["|B|^2"] + data["periodic(gbdrift)"]
)
return data


Expand Down
12 changes: 10 additions & 2 deletions desc/grid.py
Original file line number Diff line number Diff line change
Expand Up @@ -671,6 +671,7 @@ class Grid(_Grid):
Use np.inf to denote no periodicity.
NFP : int
Number of field periods (Default = 1).
Change this only if your nodes are placed within one field period.
source_grid : Grid
Grid from which coordinates were mapped from.
sort : bool
Expand Down Expand Up @@ -794,7 +795,8 @@ def create_meshgrid(
NFP : int
Number of field periods (Default = 1).
Only makes sense to change from 1 if last coordinate is periodic
with some constant divided by ``NFP``.
with some constant divided by ``NFP`` and the nodes are placed
within one field period.

Returns
-------
Expand Down Expand Up @@ -916,6 +918,8 @@ class LinearGrid(_Grid):
Toroidal grid resolution.
NFP : int
Number of field periods (Default = 1).
Change this only if your nodes are placed within one field period
or should be interpreted as spanning one field period.
sym : bool
True for stellarator symmetry, False otherwise (Default = False).
axis : bool
Expand Down Expand Up @@ -1011,6 +1015,8 @@ def _create_nodes( # noqa: C901
Toroidal grid resolution.
NFP : int
Number of field periods (Default = 1).
Only change this if your nodes are placed within one field period
or should be interpreted as spanning one field period.
axis : bool
True to include a point at rho=0 (default), False for rho[0] = rho[1]/2.
endpoint : bool
Expand All @@ -1037,8 +1043,10 @@ def _create_nodes( # noqa: C901
"""
self._NFP = check_posint(NFP, "NFP", False)
self._period = (np.inf, 2 * np.pi, 2 * np.pi / self._NFP)
# TODO:
# FIXME:
# https://github.com/PlasmaControl/DESC/pull/1204#pullrequestreview-2246771337
# Quantities like alpha, grad(alpha), etc. are computed incorrectly at
# phi > 2pi / NFP and theta > 2pi / NFP.
axis = bool(axis)
endpoint = bool(endpoint)
theta_period = self.period[1]
Expand Down
2 changes: 1 addition & 1 deletion desc/integrals/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""Classes for function integration."""

from .bounce_integral import Bounce1D
from .bounce_integral import Bounce1D, Bounce2D
from .singularities import (
DFTInterpolator,
FFTInterpolator,
Expand Down
Loading
Loading