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

Effective ripple ε #1003

Open
wants to merge 213 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
213 commits
Select commit Hold shift + click to select a range
8090374
Add epsilon effective calculion
unalmis Apr 20, 2024
6ac2251
Add trapezoidal integration to compute db integral
unalmis Apr 21, 2024
c02306b
Prepare for merge with bounce
unalmis Apr 21, 2024
bcaece0
Merge branch 'bounce' into ripple
unalmis Apr 21, 2024
f156083
Rewrite epsilon_effective computation
unalmis Apr 21, 2024
19c6413
Merge branch 'bounce' into ripple
unalmis Apr 21, 2024
f26e80d
Merge branch 'install' into ripple
unalmis Apr 21, 2024
452416a
Merge branch 'bounce' into ripple
rahulgaur104 Apr 22, 2024
f7f68d4
Merge branch 'bounce' into ripple
unalmis Apr 22, 2024
de9bc71
Add max_tz B to b values in integral for effective ripple
unalmis Apr 22, 2024
447c682
Merge branch 'bounce' into ripple
unalmis Apr 22, 2024
14ac6a7
Note to use cvdrift0
unalmis Apr 22, 2024
ce1fe11
Merge branch 'bounce' into ripple
unalmis Apr 24, 2024
cd5094e
Fix catostrophic floating point error in epsilon effective computation
unalmis Apr 24, 2024
71de921
Merge branch 'bounce' into ripple
unalmis Apr 24, 2024
a879376
Merge branch 'bounce' into ripple
unalmis Apr 24, 2024
f17c773
Merge branch 'bounce' into ripple
unalmis Apr 24, 2024
406d07d
Merge branch 'bounce' into ripple
unalmis Apr 24, 2024
558f623
Merge branch 'bounce' into ripple
unalmis Apr 24, 2024
bebc40b
Refactor effective ripple compute fun
unalmis Apr 24, 2024
b13d7ad
Split effective ripple compute function
unalmis Apr 24, 2024
7c82470
Merge branch 'bounce' into ripple
unalmis Apr 25, 2024
6074f7b
Merge branch 'bounce' into ripple
unalmis Apr 25, 2024
169556f
Write ripple compute fun with new bounce integral api
unalmis Apr 25, 2024
5044624
Merge branch 'bounce' into ripple
unalmis Apr 26, 2024
a647856
Add support for quadax adaptive integration
unalmis Apr 26, 2024
974244d
Merge branch 'bounce' into ripple
unalmis Apr 27, 2024
ad020f2
Merge branch 'bounce' into ripple
unalmis Apr 27, 2024
a7c43d7
Merge branch 'bounce' into ripple
unalmis Apr 28, 2024
9978728
Merge branch 'bounce' into ripple
unalmis Apr 28, 2024
5670703
Merge branch 'bounce' into ripple
unalmis Apr 28, 2024
75fb132
Merge branch 'bounce' into ripple
unalmis Apr 29, 2024
e848f91
Fix bug with recomputing quantities on incorrect grid
unalmis Apr 29, 2024
263a15b
Epsilon effective ready for accuracy testing
unalmis Apr 29, 2024
93ff35b
Add orthax to requiments
unalmis Apr 29, 2024
eb0088c
Merge branch 'bounce' into ripple
unalmis Apr 29, 2024
540a69e
Merge branch 'eq_compute_bug' into ripple
unalmis Apr 29, 2024
de71838
Use R0 in eps_eff
unalmis Apr 29, 2024
f2f187c
Merge branch 'bounce' into ripple
unalmis Apr 29, 2024
35ada77
Merge branch 'map_coords_missing_params' into ripple
unalmis Apr 30, 2024
0fa255d
Add eps_eff results
unalmis Apr 30, 2024
b955d7e
Fix logic bug in algorithm for first integration width
unalmis Apr 30, 2024
fa404b2
Fix eps_eff computation
unalmis May 1, 2024
468baf6
Merge branch 'bounce' into ripple
unalmis May 1, 2024
8a02352
Merge branch 'bounce' into ripple
unalmis May 1, 2024
01f8a75
Try going further along field line now that memory is used less
unalmis May 1, 2024
e5358b5
Merge branch 'bounce' into ripple
unalmis May 1, 2024
1a49329
Simplify non batched interpolation
unalmis May 1, 2024
f448bf0
Merge branch 'bounce' into ripple
unalmis May 1, 2024
b4ca7e3
Always set batched to false
unalmis May 1, 2024
6c0581c
Merge branch 'bounce' into ripple
unalmis May 1, 2024
65994a5
Merge branch 'bounce' into ripple
unalmis May 2, 2024
b08b3c0
Merge branch 'bounce' into ripple
unalmis May 3, 2024
a4637ea
Switch to quadrature that converges
unalmis May 3, 2024
490da1f
Merge branch 'bounce' into ripple
unalmis May 5, 2024
061f75b
Merge branch 'bounce' into ripple
unalmis May 9, 2024
d707531
Merge branch 'master' into ripple
unalmis May 19, 2024
91a76e0
Merge branch 'bounce' into ripple
unalmis May 22, 2024
0cc5c72
Update neoclassical compute api for changes introduced in pull reques…
unalmis May 22, 2024
229ab46
Merge branch 'bounce' into ripple
unalmis May 23, 2024
4dc1fa1
Merge branch 'bounce' into ripple
unalmis May 26, 2024
0901d96
Adaptive quadrature working now. Also reduced memory and increase speed.
unalmis May 27, 2024
95ce834
Wrap jit at outer level
unalmis May 27, 2024
fe0b099
Avoid unnecessary intermediate computation in computing ripple
unalmis May 27, 2024
34ff754
Use uniform quadrature over pitch integral because fat banana orbits …
unalmis May 27, 2024
e6183c5
Add neemov gamma_c
unalmis May 28, 2024
c5b5d69
Fix units and naming schemes, remove jit around compute fun
unalmis May 28, 2024
c333a53
Merge branch 'bounce' into ripple
unalmis May 28, 2024
c264cff
Integrate over λ instead of b.
unalmis May 29, 2024
599f895
making progress on neoclassical stuff
unalmis May 29, 2024
bc6b982
Fix math, results look kinda good now
unalmis May 30, 2024
beade78
Merge branch 'bounce' into ripple
unalmis May 31, 2024
808806c
Fix units after change of variables
unalmis May 31, 2024
b87ca1a
Fix comment discussing Nemov and Velasco Gamma_c
unalmis May 31, 2024
169af3a
Add neo comparison utitilies
unalmis May 31, 2024
f2687b6
Merge branch 'bounce' into ripple
unalmis Jun 2, 2024
50a0810
Merge branch 'bounce' into ripple
unalmis Jun 2, 2024
a9feffd
Detach Gamma_c
unalmis Jun 2, 2024
ae700f0
Merge branch 'bounce' into ripple
unalmis Jun 3, 2024
b45c0dc
Update things after merge
unalmis Jun 3, 2024
45493ae
Merge branch 'bounce' into ripple
unalmis Jun 3, 2024
bc17c5d
Merge branch 'bounce' into ripple
unalmis Jun 4, 2024
a2903cb
Normalize effective ripple by B_0 = max_tz |B| instead of B_0 = 1.
unalmis Jun 8, 2024
9d58c4e
Merge branch 'bounce' into ripple
unalmis Jun 10, 2024
c5b1fbf
Merge branch 'bounce' into ripple
unalmis Jun 11, 2024
57d6f7f
Add test and notes
unalmis Jun 11, 2024
2737194
Add baseline image test for W7-X effective ripple
unalmis Jun 11, 2024
104b3b4
Reduce memory usage in tests_neoclassical
unalmis Jun 11, 2024
4454500
Interpolate |∇ψ| κ_g together since it is smoother than κ_g alone.
unalmis Jun 12, 2024
db8b7be
Merge branch 'bounce' into ripple
unalmis Jun 12, 2024
66b24a5
Add effective ripple objective function
unalmis Jun 13, 2024
bf981dd
Add effective ripple magnetic axis limit
unalmis Jun 13, 2024
3c2aabd
Fix effective ripple label
unalmis Jun 13, 2024
4db2468
Fix doc build, and reduce first order dependency amount for effective…
unalmis Jun 13, 2024
7b5b7c0
Fix wrong alpha_t calculation and add grad(|B|)*b test
unalmis Jun 15, 2024
2dbfeb0
Add quantities in attempt to debug length derivative along field line…
unalmis Jun 17, 2024
2d01ef4
Add finite difference test or parallel gradient
unalmis Jun 17, 2024
cce1018
Merge branch 'bounce' into ripple
unalmis Jun 18, 2024
12b39c9
Fix bug with sign of derivative in effective ripple...
unalmis Jun 18, 2024
2e730bd
Partially undo previous commit --
unalmis Jun 18, 2024
d1c7d4a
Merge branch 'bounce' into ripple
unalmis Jun 18, 2024
9c68b41
No more nan in effective ripple gradient
unalmis Jun 22, 2024
f0ac159
Merge branch 'bounce' into ripple
unalmis Jun 22, 2024
6a3965c
Merge branch 'bounce' into ripple
unalmis Jun 22, 2024
fc1be1c
Add equilibrium.rtz_grid method to avoid circular import and update d…
unalmis Jun 24, 2024
0319dca
Mark test_parallel_grad xfail
unalmis Jun 24, 2024
9dc81b3
Merge branch 'bounce' into ripple
unalmis Jun 25, 2024
38d82a7
average before integration to reduce computation
unalmis Jun 25, 2024
381543f
Merge branch bounce into ripple
unalmis Jun 28, 2024
54dab1a
Merge branch 'bounce' into ripple
unalmis Jul 1, 2024
4b3983e
Do review suggestions, remove Quadrature grid from ripple objective
unalmis Jul 2, 2024
3f75c09
Merge branch 'bounce' into ripple
unalmis Jul 2, 2024
ee437ea
Merge branch 'bounce' into ripple
unalmis Jul 2, 2024
96ac3e9
Merge branch 'bounce' into ripple
unalmis Jul 5, 2024
6827fcd
Fix comment
unalmis Jul 5, 2024
0c995d1
Merge with Clebsch branch
unalmis Jul 8, 2024
8a8d9de
Merge branch 'bounce' into ripple and clean up bloated test so that I…
unalmis Jul 11, 2024
97e081f
Leftover merge conflicts
unalmis Jul 11, 2024
9f1371b
Merge branch 'clebsh_basis' into ripple
unalmis Jul 11, 2024
ce1c280
Merge branch 'bounce' into ripple
unalmis Jul 20, 2024
a28dade
Remove no longer needed jitable argument in get_profiles
unalmis Jul 20, 2024
ea6e0dc
Merge branch 'bounce' into ripple
unalmis Jul 24, 2024
5409b40
Merge branch 'bounce' into ripple
unalmis Jul 25, 2024
10ac679
Update master compute data
unalmis Jul 25, 2024
f54abb4
Update master compute data again
unalmis Jul 25, 2024
5d61f58
Only get profiles in build of objective
unalmis Jul 25, 2024
3e49a8b
Merge branch 'bounce' into ripple
unalmis Jul 25, 2024
84d1134
Merge branch 'bounce' into ripple
unalmis Jul 25, 2024
68efde6
Add num_wells parameter to increase performance
unalmis Jul 25, 2024
a8bbbc9
Merge branch 'bounce' into ripple
unalmis Jul 25, 2024
5fb62bf
Add num_wells to objective
unalmis Jul 25, 2024
c1c6c16
Merge branch 'bounce' into ripple
unalmis Jul 26, 2024
a603df2
Add num_wells as static variables to compute fun
unalmis Jul 26, 2024
70a3e43
Use kwargs in simpson integral to match API change in quadax from las…
unalmis Jul 26, 2024
661e6cd
Merge branch 'bounce' into ripple
unalmis Aug 7, 2024
a3e1ba4
Take mean later since doesn't matter for speed and easier to do multi…
unalmis Aug 18, 2024
fb13f31
Merge branch 'bounce' into ripple
unalmis Aug 18, 2024
cbeda22
Merge branch 'ku/root_3d' into ripple
unalmis Aug 18, 2024
5b0393e
Merge branch 'bounce' into ripple
unalmis Aug 20, 2024
36428d3
Merge branch 'bounce' into ripple
unalmis Sep 1, 2024
d952252
Merge branch 'bounce' into ripple
unalmis Sep 1, 2024
4e9ebb9
Update effective ripple computation for all changes in upstream branches
unalmis Sep 2, 2024
9ff79da
Merge branch 'utils' into ripple
unalmis Sep 2, 2024
04a0d52
Remove test that is now redue to test with effective ripple
unalmis Sep 2, 2024
b383358
Merge branch 'bounce' into ripple
unalmis Sep 3, 2024
654a5ff
Same as commit f596dc6 and d382df3
unalmis Sep 3, 2024
9e80037
Fixing Pycharm's automated refactor
unalmis Sep 3, 2024
a93a6da
Merge branch 'master' into ripple
unalmis Sep 3, 2024
0f319e0
Merge branch 'utils' into ripple
unalmis Sep 3, 2024
8d5f3d3
Remove adaptive quadrature for now
unalmis Sep 3, 2024
3b1ffc0
Merge branch 'utils' into ripple
unalmis Sep 3, 2024
3b5441f
Allow kwargs to bounce.plot
unalmis Sep 4, 2024
fd914e8
Merge branch 'utils' into ripple
unalmis Sep 4, 2024
f2c26d9
Merge branch 'utils' into ripple
unalmis Sep 4, 2024
9d981ff
Update effective ripple objective to work with recent changes to master
unalmis Sep 4, 2024
456d1a8
atone for pycharm's bad automated refactor commit number 3
unalmis Sep 4, 2024
fc8b393
Merge branch 'master' into ripple
f0uriest Sep 6, 2024
598009f
Merge commit 'fc8b393' into ripple
unalmis Sep 15, 2024
d266505
Merge branch 'master' into ripple
unalmis Sep 15, 2024
9a968e6
Compute quadrature nodes once outside objective.compute
unalmis Sep 15, 2024
b4151d9
Fix nan leak in reverse mode ad for bounce integral
unalmis Sep 15, 2024
8b656f2
Fix comment that one poloidal transit is sufficient if axissymetric
unalmis Sep 15, 2024
3a93117
Use _constants instead of constants
unalmis Sep 15, 2024
52adba9
Improve quadrature over velocity coordiante for effective ripple
unalmis Sep 16, 2024
8d9b605
Cleaner solution to b4151d9
unalmis Sep 16, 2024
5bc4b35
Simplify computation of quad points
unalmis Sep 16, 2024
6146dc4
Remove now unnecessary code
unalmis Sep 16, 2024
0366137
Better quadrature for weakly singular bounce integrals
unalmis Sep 17, 2024
6a46efb
fix comment about change of variable
unalmis Sep 17, 2024
bd68679
Use interior nodes only for more fair test
unalmis Sep 17, 2024
06d5061
Add documentation on which quadrature to use
unalmis Sep 17, 2024
53fd368
Merge branch 'master' into ripple
unalmis Sep 18, 2024
454bf3b
Merge branch 'master' into ripple
unalmis Sep 18, 2024
41f3727
Increase test_compute_everything tolerance
unalmis Sep 18, 2024
6e3b0e7
Merge branch 'master' into ripple
unalmis Sep 19, 2024
e2b58c7
Removing period argument
unalmis Sep 19, 2024
df0590b
Merge branch 'ku/fourier_bounce_part1' into ripple
unalmis Sep 22, 2024
4756c38
Merge branch 'ku/fourier_bounce_part1' into ripple
unalmis Sep 22, 2024
2073547
Avoid redundant computation of bounce points
unalmis Sep 22, 2024
e5d150c
Merge branch 'ku/fourier_bounce_part1' into ripple
unalmis Sep 22, 2024
1edd349
Complete @f0uriest 's request to compare against Neo
unalmis Sep 22, 2024
850001a
Add neo out file to desc repository
unalmis Sep 22, 2024
0ae5c9a
Do remaining review suggestion
unalmis Sep 22, 2024
8cb2a28
Fix linear interpolation for bad neo values
unalmis Sep 22, 2024
21235b4
Fix neo script
unalmis Sep 22, 2024
098db02
Merge branch 'ku/fourier_bounce_part1' into ripple
unalmis Sep 22, 2024
eb3370b
Merge branch 'ku/fourier_bounce_part1' into ripple
unalmis Sep 24, 2024
56a88a8
Update _write_neo
unalmis Sep 24, 2024
9e88270
Merge branch 'master' into ripple
unalmis Sep 24, 2024
8840c9c
Review suggestions
unalmis Sep 24, 2024
2dffde2
Add epsilon 3/2 and effective ripple as distinct
unalmis Sep 25, 2024
73a6b48
Increase entropy of test compute everything to pass test
unalmis Sep 26, 2024
6c1cd12
Fix DESC docs variable name
unalmis Sep 26, 2024
5b4456d
Merge branch 'master' into ripple
unalmis Sep 26, 2024
7d88eac
Simplify latex label
unalmis Sep 26, 2024
c819e32
Merge branch 'master' into ripple
unalmis Sep 26, 2024
157e57b
Add chunk size option
unalmis Sep 26, 2024
883b34d
Merge branch 'master' into ripple
unalmis Sep 27, 2024
1b3b6f2
Fix name in test
unalmis Sep 27, 2024
a2a3d71
Merge branch 'master' into ripple
rahulgaur104 Sep 27, 2024
3e4c0ab
Review requests and refactor to avoid explicit broadcast
unalmis Sep 29, 2024
998c830
Clean up
unalmis Sep 29, 2024
499a6c7
Move changes from downstream branch here
unalmis Sep 30, 2024
71b42bd
Merge branch 'master' into ripple
unalmis Sep 30, 2024
e5bfd38
Merge branch 'master' into ripple
rahulgaur104 Oct 4, 2024
ae939e9
Merge branch 'master' into ripple
unalmis Oct 17, 2024
569dcdc
Merge branch 'master' into ripple
unalmis Oct 17, 2024
59235b0
Update baseline image now that plot_fsa computes on symmetric grid
unalmis Oct 17, 2024
78fa50d
Merge branch 'master' into ripple
dpanici Oct 17, 2024
c2971d1
adding ripple notebook with rev-mode optimization example
rahulgaur104 Oct 18, 2024
d3d239e
Add missing unit test marker to nangrad ballooning
unalmis Oct 19, 2024
0dd088b
Add riple tutorial to docs to avoid failing test
unalmis Oct 19, 2024
47744c2
Change variable name <L|r,a> to fieldline length
unalmis Oct 20, 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
1 change: 1 addition & 0 deletions desc/compute/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
_field,
_geometry,
_metric,
_neoclassical,
_omnigenity,
_profiles,
_stability,
Expand Down
4 changes: 2 additions & 2 deletions desc/compute/_equil.py
Original file line number Diff line number Diff line change
Expand Up @@ -658,12 +658,12 @@ def _F_anisotropic(params, transforms, profiles, data, **kwargs):
transforms={"grid": []},
profiles=[],
coordinates="",
data=["|B|", "sqrt(g)"],
data=["|B|^2", "sqrt(g)"],
resolution_requirement="rtz",
)
def _W_B(params, transforms, profiles, data, **kwargs):
data["W_B"] = jnp.sum(
data["|B|"] ** 2 * data["sqrt(g)"] * transforms["grid"].weights
data["|B|^2"] * data["sqrt(g)"] * transforms["grid"].weights
) / (2 * mu_0)
return data

Expand Down
272 changes: 272 additions & 0 deletions desc/compute/_neoclassical.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,272 @@
"""Compute functions for neoclassical transport.

Notes
-----
Some quantities require additional work to compute at the magnetic axis.
A Python lambda function is used to lazily compute the magnetic axis limits
of these quantities. These lambda functions are evaluated only when the
computational grid has a node on the magnetic axis to avoid potentially
expensive computations.
"""

from functools import partial

from quadax import simpson

from desc.backend import imap, jit, jnp

from ..integrals.bounce_integral import Bounce1D
from ..integrals.bounce_utils import get_pitch_inv_quad
from ..integrals.quad_utils import chebgauss2
from ..utils import safediv
from .data_index import register_compute_fun

_bounce_doc = {
"quad": (
"tuple[jnp.ndarray] : Quadrature points and weights for bounce integrals. "
"Default option is well tested."
),
"num_quad": (
"int : Resolution for quadrature of bounce integrals. "
"Default is 32. This option is ignored if given ``quad``."
),
"num_pitch": "int : Resolution for quadrature over velocity coordinate.",
"num_well": (
"int : Maximum number of wells to detect for each pitch and field line. "
"Default is to detect all wells, but due to limitations in JAX this option "
"may consume more memory. Specifying a number that tightly upper bounds "
"the number of wells will increase performance."
),
"batch": "bool : Whether to vectorize part of the computation. Default is true.",
}


def _alpha_mean(f):
"""Simple mean over field lines.

Simple mean rather than integrating over α and dividing by 2π
(i.e. f.T.dot(dα) / dα.sum()), because when the toroidal angle extends
beyond one transit we need to weight all field lines uniformly, regardless
of their spacing wrt α.
"""
return f.mean(axis=0)


def _compute(fun, interp_data, data, grid, num_pitch, reduce=True):
"""Compute ``fun`` for each α and ρ value iteratively to reduce memory usage.

Parameters
----------
fun : callable
Function to compute.
interp_data : dict[str, jnp.ndarray]
Data to provide to ``fun``.
Names in ``Bounce1D.required_names`` will be overridden.
Reshaped automatically.
data : dict[str, jnp.ndarray]
DESC data dict.
reduce : bool
Whether to compute mean over α and expand to grid.
Default is true.

"""
pitch_inv, pitch_inv_weight = get_pitch_inv_quad(
grid.compress(data["min_tz |B|"]),
grid.compress(data["max_tz |B|"]),
num_pitch,
)

def for_each_rho(x):
# using same λ values for every field line α on flux surface ρ
x["pitch_inv"] = pitch_inv
x["pitch_inv weight"] = pitch_inv_weight
return imap(fun, x)

for name in Bounce1D.required_names:
interp_data[name] = data[name]
interp_data = dict(
zip(interp_data.keys(), Bounce1D.reshape_data(grid, *interp_data.values()))
)
out = imap(for_each_rho, interp_data)
return grid.expand(_alpha_mean(out)) if reduce else out


@register_compute_fun(
name="fieldline length",
label="\\int_{\\zeta_{\\mathrm{min}}}^{\\zeta_{\\mathrm{max}}}"
" \\frac{d\\zeta}{|B^{\\zeta}|}",
units="m / T",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are we missing a factor to make this have units of length?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has the desired units. dhaeseleer calls this the proper length, (p.g. VIII and chapter 12)

units_long="Meter / tesla",
description="(Mean) proper length of field line(s)",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a non-rational field line is formally infinite in length, is this taking the "length" over 1 toroidal turn?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's the length of your sample of the field line. Yes, this converges to infinity.

dim=1,
params=[],
transforms={"grid": []},
profiles=[],
coordinates="r",
data=["B^zeta"],
resolution_requirement="z",
source_grid_requirement={"coordinates": "raz", "is_meshgrid": True},
)
def _fieldline_length(data, transforms, profiles, **kwargs):
grid = transforms["grid"].source_grid
L_ra = simpson(
y=grid.meshgrid_reshape(1 / data["B^zeta"], "arz"),
x=grid.compress(grid.nodes[:, 2], surface_label="zeta"),
axis=-1,
)
data["fieldline length"] = grid.expand(jnp.abs(_alpha_mean(L_ra)))
return data


@register_compute_fun(
name="fieldline length/volume",
label="\\int_{\\zeta_{\\mathrm{min}}}^{\\zeta_{\\mathrm{max}}}"
" \\frac{d\\zeta}{|B^{\\zeta} \\sqrt g|}",
units="1 / Wb",
units_long="Inverse webers",
description="(Mean) proper length over volume of field line(s)",
dim=1,
params=[],
transforms={"grid": []},
profiles=[],
coordinates="r",
data=["B^zeta", "sqrt(g)"],
resolution_requirement="z",
source_grid_requirement={"coordinates": "raz", "is_meshgrid": True},
)
def _fieldline_length_over_volume(data, transforms, profiles, **kwargs):
grid = transforms["grid"].source_grid
G_ra = simpson(
y=grid.meshgrid_reshape(1 / (data["B^zeta"] * data["sqrt(g)"]), "arz"),
x=grid.compress(grid.nodes[:, 2], surface_label="zeta"),
axis=-1,
)
data["fieldline length/volume"] = grid.expand(jnp.abs(_alpha_mean(G_ra)))
return data


@register_compute_fun(
name="effective ripple 3/2",
label=(
# ε¹ᐧ⁵ = π/(8√2) R₀²〈|∇ψ|〉⁻² B₀⁻¹ ∫dλ λ⁻² 〈 ∑ⱼ Hⱼ²/Iⱼ 〉
"\\epsilon_{\\mathrm{eff}}^{3/2} = \\frac{\\pi}{8 \\sqrt{2}} "
"R_0^2 \\langle \\vert\\nabla \\psi\\vert \\rangle^{-2} "
"B_0^{-1} \\int d\\lambda \\lambda^{-2} "
"\\langle \\sum_j H_j^2 / I_j \\rangle"
),
units="~",
units_long="None",
description="Effective ripple modulation amplitude to 3/2 power",
dim=1,
params=[],
transforms={"grid": []},
profiles=[],
coordinates="r",
data=[
"min_tz |B|",
"max_tz |B|",
"kappa_g",
"R0",
"|grad(rho)|",
"<|grad(rho)|>",
"fieldline length",
]
+ Bounce1D.required_names,
resolution_requirement="z",
source_grid_requirement={"coordinates": "raz", "is_meshgrid": True},
**_bounce_doc,
# Some notes on choosing the resolution hyperparameters:
# The default settings were chosen such that the effective ripple profile on
# the W7-X stellarator looks similar to the profile computed at higher resolution,
f0uriest marked this conversation as resolved.
Show resolved Hide resolved
# indicating convergence. The parameters ``num_transit`` and ``knots_per_transit``
# have a stronger effect on the result. As a reference for W7-X, when computing the
# effective ripple by tracing a single field line on each flux surface, a density of
# 100 knots per toroidal transit accurately reconstructs the ripples along the field
# line. After 10 toroidal transits convergence is apparent (after 15 the returns
# diminish). Dips in the resulting profile indicates insufficient ``num_transit``.
# Unreasonably high values indicates insufficient ``knots_per_transit``.
# One can plot the field line with ``Bounce1D.plot`` to see if the number of knots
# was sufficient to reconstruct the field line.
# TODO: Improve performance... see GitHub issue #1045.
# Need more efficient function approximation of |B|(α, ζ).
)
@partial(jit, static_argnames=["num_quad", "num_pitch", "num_well", "batch"])
def _epsilon_32(params, transforms, profiles, data, **kwargs):
"""https://doi.org/10.1063/1.873749.

Evaluation of 1/ν neoclassical transport in stellarators.
V. V. Nemov, S. V. Kasilov, W. Kernbichler, M. F. Heyn.
Phys. Plasmas 1 December 1999; 6 (12): 4622–4632.
"""
# noqa: unused dependency
if "quad" in kwargs:
quad = kwargs["quad"]
else:
quad = chebgauss2(kwargs.get("num_quad", 32))
num_well = kwargs.get("num_well", None)
batch = kwargs.get("batch", True)
grid = transforms["grid"].source_grid

def dH(grad_rho_norm_kappa_g, B, pitch):
# Integrand of Nemov eq. 30 with |∂ψ/∂ρ| (λB₀)¹ᐧ⁵ removed.
f0uriest marked this conversation as resolved.
Show resolved Hide resolved
return (
jnp.sqrt(jnp.abs(1 - pitch * B))
* (4 / (pitch * B) - 1)
* grad_rho_norm_kappa_g
/ B
)

def dI(B, pitch):
# Integrand of Nemov eq. 31.
return jnp.sqrt(jnp.abs(1 - pitch * B)) / B
f0uriest marked this conversation as resolved.
Show resolved Hide resolved

def eps_32(data):
"""(∂ψ/∂ρ)⁻² B₀⁻² ∫ dλ λ⁻² ∑ⱼ Hⱼ²/Iⱼ."""
# B₀ has units of λ⁻¹.
# Nemov's ∑ⱼ Hⱼ²/Iⱼ = (∂ψ/∂ρ)² (λB₀)³ ``(H**2 / I).sum(axis=-1)``.
# (λB₀)³ d(λB₀)⁻¹ = B₀² λ³ d(λ⁻¹) = -B₀² λ dλ.
bounce = Bounce1D(grid, data, quad, automorphism=None, is_reshaped=True)
points = bounce.points(data["pitch_inv"], num_well=num_well)
H = bounce.integrate(
dH,
data["pitch_inv"],
data["|grad(rho)|*kappa_g"],
points=points,
batch=batch,
)
I = bounce.integrate(dI, data["pitch_inv"], points=points, batch=batch)
return (
safediv(H**2, I).sum(axis=-1)
* data["pitch_inv"] ** (-3)
* data["pitch_inv weight"]
).sum(axis=-1)

# Interpolate |∇ρ| κ_g since it is smoother than κ_g alone.
interp_data = {"|grad(rho)|*kappa_g": data["|grad(rho)|"] * data["kappa_g"]}
B0 = data["max_tz |B|"]
data["effective ripple 3/2"] = (
jnp.pi
/ (8 * 2**0.5)
* (B0 * data["R0"] / data["<|grad(rho)|>"]) ** 2
* _compute(eps_32, interp_data, data, grid, kwargs.get("num_pitch", 50))
/ data["fieldline length"]
)
return data


@register_compute_fun(
name="effective ripple",
label="\\epsilon_{\\mathrm{eff}}",
units="~",
units_long="None",
description="Effective ripple modulation amplitude",
dim=1,
params=[],
transforms={},
profiles=[],
coordinates="r",
data=["effective ripple 3/2"],
)
def _effective_ripple(params, transforms, profiles, data, **kwargs):
data["effective ripple"] = data["effective ripple 3/2"] ** (2 / 3)
return data
4 changes: 2 additions & 2 deletions desc/compute/_omnigenity.py
Original file line number Diff line number Diff line change
Expand Up @@ -608,10 +608,10 @@ def _B_omni(params, transforms, profiles, data, **kwargs):
transforms={},
profiles=[],
coordinates="rtz",
data=["b", "grad(|B|)", "|B|", "grad(psi)"],
data=["b", "grad(|B|)", "|B|^2", "grad(psi)"],
)
def _isodynamicity(params, transforms, profiles, data, **kwargs):
data["isodynamicity"] = (
dot(cross(data["b"], data["grad(|B|)"]), data["grad(psi)"]) / data["|B|"] ** 2
dot(cross(data["b"], data["grad(|B|)"]), data["grad(psi)"]) / data["|B|^2"]
)
return data
10 changes: 7 additions & 3 deletions desc/compute/_profiles.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@
expensive computations.
"""

from quadax import cumulative_simpson
from scipy.constants import elementary_charge, mu_0

from desc.backend import cond, jnp

from ..integrals.surface_integral import surface_averages, surface_integrals
from ..utils import cumtrapz, dot, safediv
from ..utils import dot, safediv
from .data_index import register_compute_fun


Expand Down Expand Up @@ -142,8 +143,11 @@ def _chi_r(params, transforms, profiles, data, **kwargs):
resolution_requirement="r",
)
def _chi(params, transforms, profiles, data, **kwargs):
chi_r = transforms["grid"].compress(data["chi_r"])
chi = cumtrapz(chi_r, transforms["grid"].compress(data["rho"]), initial=0)
chi = cumulative_simpson(
y=transforms["grid"].compress(data["chi_r"]),
x=transforms["grid"].compress(data["rho"]),
initial=0,
)
data["chi"] = transforms["grid"].expand(chi)
return data

Expand Down
2 changes: 1 addition & 1 deletion desc/compute/_stability.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""Compute functions for Mercier stability objectives.
"""Compute functions for stability objectives.
Notes
-----
Expand Down
15 changes: 11 additions & 4 deletions desc/equilibrium/equilibrium.py
Original file line number Diff line number Diff line change
Expand Up @@ -1221,8 +1221,15 @@ def map_coordinates(
**kwargs,
)

def get_rtz_grid(
self, radial, poloidal, toroidal, coordinates, period, jitable=True, **kwargs
def _get_rtz_grid(
self,
radial,
poloidal,
toroidal,
coordinates,
period=(np.inf, np.inf, np.inf),
jitable=True,
**kwargs,
):
"""Return DESC grid in (rho, theta, zeta) coordinates from given coordinates.

Expand All @@ -1243,8 +1250,8 @@ def get_rtz_grid(
rvp : rho, theta_PEST, phi
rtz : rho, theta, zeta
period : tuple of float
Assumed periodicity for each quantity in inbasis.
Use np.inf to denote no periodicity.
Assumed periodicity of the given coordinates.
Use ``np.inf`` to denote no periodicity.
jitable : bool, optional
If false the returned grid has additional attributes.
Required to be false to retain nodes at magnetic axis.
Expand Down
2 changes: 1 addition & 1 deletion desc/integrals/quad_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def automorphism_sin(x, s=0, m=10):
"""[-1, 1] ∋ x ↦ y ∈ [−1, 1].

This map increases node density near the boundary by the asymptotic factor
1/√(1−x²) and adds a √(1−x²) factor to the integrand.
1/√(1−x²) and adds a cosine factor to the integrand.

Parameters
----------
Expand Down
1 change: 1 addition & 0 deletions desc/objectives/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
PrincipalCurvature,
Volume,
)
from ._neoclassical import EffectiveRipple
from ._omnigenity import (
Isodynamicity,
Omnigenity,
Expand Down
Loading