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

Add Ability to Write Boozmn.nc style output files #680

Merged
merged 136 commits into from
Feb 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
136 commits
Select commit Hold shift + click to select a range
72da051
first commit, machinery working but need to figure out good way to fi…
dpanici Sep 19, 2023
efb9245
properly save nu_mn and zmns using sin bases when equilibrium is stel…
dpanici Sep 25, 2023
a15b3f3
fix Z_mn and nu_mn calculations by having them use the correct values…
dpanici Sep 25, 2023
64b9b29
rename sqrt(g)_B to jac_Boozer_DESC for clarity, add proper sqrt(g)_B…
dpanici Sep 25, 2023
d20de7a
Merge branch 'master' into dp/boozmn_style_output
dpanici Sep 25, 2023
a11e1ab
fix extra/lacking dependencies
dpanici Sep 26, 2023
279535b
add missing file.close(), change test to use get instead of solving H…
dpanici Sep 26, 2023
7aa6318
Merge branch 'master' into dp/boozmn_style_output
dpanici Nov 8, 2023
1600f49
correct signs of sin(theta) modes before conversion in boozmn output …
dpanici Nov 9, 2023
36749f6
add test against c++ version of booz_xform
dpanici Nov 9, 2023
84fd8f7
fix test half grid
dpanici Nov 9, 2023
2aed44e
Merge branch 'master' into dp/boozmn_style_output
dpanici Nov 9, 2023
8a1f5b8
fix boozmn test
dpanici Nov 9, 2023
4a0014f
reduce grid resolution for boozmn
dpanici Nov 9, 2023
31614d8
precompute quantities that don't need to use a single surface grid in…
dpanici Nov 9, 2023
46f1eda
add more precomputed quantities
dpanici Nov 9, 2023
5e69f19
Merge branch 'master' into dp/boozmn_style_output
dpanici Nov 9, 2023
40e24c8
precompute fitted quanttities (B_theta_mn and B_zeta_mn), add option …
dpanici Nov 10, 2023
b2d9ca4
fix error in logic in zernike to fourier util
dpanici Nov 10, 2023
b3b8e04
update master data pkl bc sqrt(g)_B changed definition
dpanici Nov 10, 2023
d3ec3eb
make computes in boozmn writing slighlty more efficient
dpanici Nov 10, 2023
4f78956
add test against most of the keys in the cpp version of boozmn
dpanici Nov 10, 2023
e1860ac
Merge branch 'master' into dp/boozmn_style_output
dpanici Nov 10, 2023
d827c78
update docstring
dpanici Nov 10, 2023
c05290f
Merge branch 'dp/boozmn_style_output' of github.com:PlasmaControl/DES…
dpanici Nov 10, 2023
0302761
update changelog
dpanici Nov 10, 2023
31ca5d1
add boozer transform prefactor to data index (the norm of the integra…
dpanici Nov 10, 2023
137c2eb
add basis evaluation to the prefactor computation, greatly speeds up …
dpanici Nov 10, 2023
8bd6497
refactor to use jit, sped up a bit (around 25% for the test)
dpanici Nov 12, 2023
eaa7d00
remove unneeded argument for comput_data_sin_sym
dpanici Nov 12, 2023
daf4e7a
update changelog, some comments, and reduce test resolution to avoid …
dpanici Nov 12, 2023
5d3585d
addres comments
dpanici Nov 12, 2023
691203f
reduce test tol
dpanici Nov 12, 2023
8b1930f
make changes to make asymmetric work, although still not completely c…
dpanici Nov 13, 2023
24166c2
add missing files for test
dpanici Nov 13, 2023
08b46f4
fixes for asymmetric boozmn output
dpanici Nov 13, 2023
3bb0683
add test against the simsopt version of C++ for asym
dpanici Nov 13, 2023
e86448e
Merge branch 'master' into dp/boozmn_style_output
dpanici Nov 13, 2023
5bc1c76
fix test paths
dpanici Nov 13, 2023
cded97b
Merge branch 'master' into dp/boozmn_style_output
dpanici Nov 14, 2023
1d14e72
rename prefactor to matrix
dpanici Nov 14, 2023
8938384
remove unneeded files, update test to use output from most recent boo…
dpanici Nov 14, 2023
537b7ec
remove unneeded files, update test to use output from most recent boo…
dpanici Nov 14, 2023
b9032b7
Merge branch 'dp/boozmn_style_output' of github.com:PlasmaControl/DES…
dpanici Nov 14, 2023
6d89589
reduce test tol for CI
dpanici Nov 15, 2023
d9646b3
Merge branch 'master' into dp/boozmn_style_output
dpanici Nov 16, 2023
f9e0619
fix units
dpanici Nov 16, 2023
4b0db03
Merge branch 'master' into dp/boozmn_style_output
dpanici Nov 16, 2023
96223bd
address comments
dpanici Nov 18, 2023
a972732
fix changed keyword
dpanici Nov 18, 2023
fa24b5a
fix compute quantity name in notebook
dpanici Nov 18, 2023
6701d38
Merge branch 'master' into dp/boozmn_style_output
dpanici Dec 2, 2023
111b8d9
remove Fourier-Zernike fitof B_theta and B_zeta as it was inaccurate,…
dpanici Dec 2, 2023
e08df50
update master pickle data
dpanici Dec 12, 2023
75b65ec
Merge branch 'master' into dp/boozmn_style_output
dpanici Dec 12, 2023
e0804a5
adjust test tol
dpanici Dec 12, 2023
fc68d35
change tests to rtol
dpanici Dec 12, 2023
4d48c7a
Merge branch 'master' into dp/boozmn_style_output
dpanici Feb 5, 2024
1fbf137
change test against cpp to test in real space, not in the Fourier coe…
dpanici Feb 5, 2024
8b220bc
remove redundant tests
dpanici Feb 5, 2024
5a4dd8b
add missing rho attribute to .h5 file
dpanici Feb 5, 2024
e0a9efb
update pkl, restore test to correct state, merge master
dpanici Feb 5, 2024
5597e24
add more description to test err msg
dpanici Feb 5, 2024
a147231
Revert "remove redundant tests"
dpanici Feb 5, 2024
230b32a
test against real space, adjust tols for the sym test
dpanici Feb 5, 2024
0db93d4
Merge branch 'master' into dp/boozmn_style_output
dpanici Mar 12, 2024
92bf4fc
Merge branch 'master' into dp/boozmn_style_output
dpanici Mar 12, 2024
3e664cf
update master data from cluster (not Mac as that causes some small di…
dpanici Mar 12, 2024
3d38ea7
resave eq with missing attributes
dpanici Mar 12, 2024
9b01ab0
add missing boozmn file
dpanici Mar 13, 2024
d47c658
loosen tol slightly
dpanici Mar 13, 2024
46d597f
Merge branch 'master' into dp/boozmn_style_output
dpanici Mar 20, 2024
86b8cc0
Merge branch 'master' into dp/boozmn_style_output
dpanici Apr 17, 2024
0a687f9
loosen rtol
dpanici Apr 17, 2024
c72360a
fix key for objective
dpanici Apr 17, 2024
3f056df
loosen asym test tol
dpanici Apr 17, 2024
aa06111
update master data by runnin on linux cluster
dpanici Apr 17, 2024
433d35c
add an atol to asym check against cpp
dpanici Apr 17, 2024
152b5f1
loosen tols
dpanici Apr 19, 2024
cc1e827
update pickle
dpanici May 8, 2024
bf97b5f
Merge branch 'master' into dp/boozmn_style_output
dpanici May 8, 2024
25d1864
change tol and grid
dpanici May 8, 2024
b1147d4
reduce tol
dpanici May 9, 2024
64e5bc6
Merge branch 'master' into dp/boozmn_style_output
dpanici May 9, 2024
ee7e016
rerun test on linux and update master data
dpanici May 9, 2024
e0035a0
Merge branch 'master' into dp/boozmn_style_output
dpanici Jun 19, 2024
bf41545
fix error in test
dpanici Jun 20, 2024
c0dc846
mark the asym comparison to cpp booz xform as xfail for now
dpanici Jun 20, 2024
c6de3fd
Merge branch 'master' into dp/boozmn_style_output
dpanici Aug 19, 2024
4a0da36
remove old kwarg
dpanici Aug 19, 2024
e53e29d
adjust tols
dpanici Aug 20, 2024
46efc0a
Merge branch 'master' into dp/boozmn_style_output
dpanici Aug 20, 2024
decbc52
Merge branch 'master' into dp/boozmn_style_output
dpanici Aug 20, 2024
f00189a
update master data in env with latest JAX version
dpanici Aug 20, 2024
4fed74d
address comments
dpanici Aug 21, 2024
1e05a2a
Merge branch 'dp/vmecio-asym' into dp/boozmn_style_output
dpanici Aug 29, 2024
6ab0cd4
Merge branch 'dp/vmecio-asym' into dp/boozmn_style_output
dpanici Aug 30, 2024
8a3e784
update boozmn
dpanici Sep 1, 2024
033e6ec
Merge branch 'master' into dp/boozmn_style_output
dpanici Sep 1, 2024
f7fb3c6
Merge branch 'master' into dp/boozmn_style_output
dpanici Sep 2, 2024
2edea11
merged branches, need to update the boozmn_output util fxn still
dpanici Dec 25, 2024
f263a26
Merge branch 'master' into dp/boozmn_style_output
dpanici Jan 9, 2025
1ab3d81
Merge branch 'master' into dp/boozmn_style_output
dpanici Jan 9, 2025
afb04fe
fix sqrtg rho->psi in boozmn output creation
dpanici Jan 11, 2025
74a08d0
fix bug in sin symmetric boozmn
dpanici Jan 12, 2025
1590f2f
change boozmn test to use precise QA
dpanici Jan 13, 2025
342a5e9
fix tol for asym test
dpanici Jan 14, 2025
4d8f088
remove asym boozmn test
dpanici Jan 14, 2025
185315f
remove unneeded files
dpanici Jan 14, 2025
276ef14
Merge branch 'master' into dp/boozmn_style_output
dpanici Jan 15, 2025
2ce7d0a
Merge branch 'master' into dp/boozmn_style_output
dpanici Jan 17, 2025
f64ceaa
Merge branch 'master' into dp/boozmn_style_output
dpanici Jan 22, 2025
4e1a066
simplify test
dpanici Jan 25, 2025
8a37f46
Merge branch 'master' into dp/boozmn_style_output
dpanici Jan 26, 2025
4e220c5
address some comments
dpanici Jan 26, 2025
82b7231
add deprecation for old sqrt(g)_B name
dpanici Jan 26, 2025
8eccfd3
add to api
dpanici Jan 26, 2025
aa2de0d
address comments in boozmn_output function
dpanici Jan 26, 2025
f2b34ce
address more comment
dpanici Jan 26, 2025
5196a0d
undo unneeded change
dpanici Jan 26, 2025
4345dc4
remove unused pkl
dpanici Jan 26, 2025
7d0a2bb
remove unused pkl and change references to _rpz.pkl
dpanici Jan 26, 2025
404b693
update pkl
dpanici Jan 26, 2025
f579d34
Merge branch 'master' into dp/boozmn_style_output
dpanici Jan 27, 2025
385e9de
update master pkl with most recent requirements file
dpanici Jan 27, 2025
fcfa68d
replace nu_mn with nu_B_mn
dpanici Jan 28, 2025
fe0ffe4
Merge branch 'master' into dp/boozmn_style_output
dpanici Jan 28, 2025
ba487f4
make |B|_mn deprecated
dpanici Jan 30, 2025
d8e2c59
update changelog, add warning for asym, and reduce test resolution
dpanici Feb 5, 2025
c1a5850
Merge branch 'master' into dp/boozmn_style_output
dpanici Feb 6, 2025
d7e6d39
Update CHANGELOG.md
dpanici Feb 6, 2025
0e48b04
Merge branch 'master' into dp/boozmn_style_output
dpanici Feb 6, 2025
b673533
Merge branch 'master' into dp/boozmn_style_output
YigitElma Feb 7, 2025
84a4236
move deprecated name in tests
dpanici Feb 7, 2025
fe4c0f2
Merge branch 'master' into dp/boozmn_style_output
dpanici Feb 9, 2025
f2b7711
update description, change some cosmetic things
dpanici Feb 10, 2025
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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ New Features
- Adds batching feature to singular integrals.
- ``desc.objectives.CoilSetMinDistance`` and ``desc.objectives.PlasmaCoilSetMinDistance`` now include the option to use a softmin which can give smoother gradients. They also both now have a ``dist_chunk_size`` option to break up the distance calculation into smaller pieces to save memory
- Adds a new function ``desc.coils.initialize_helical_coils`` for creating an initial guess for stage 2 helical coil optimization.
- Adds ``desc.vmec_utils.make_boozmn_output `` for writing boozmn.nc style output files
for compatibility with other codes which expect such files from the Booz_Xform code.
- Renames compute quantity ``sqrt(g)_B`` to ``sqrt(g)_Boozer_DESC`` to more accurately reflect what the quantiy is (the jacobian from (rho,theta_B,zeta_B) to (rho,theta,zeta)), and adds a new function to compute ``sqrt(g)_Boozer`` which is the jacobian from (rho,theta_B,zeta_B) to (R,phi,Z).
- Allows specification of Nyquist spectrum maximum modenumbers when using ``VMECIO.save`` to save a DESC .h5 file as a VMEC-format wout file

Bug Fixes

Expand Down
3 changes: 3 additions & 0 deletions CONTRIBUTING.rst
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,9 @@ If the 2nd case is the reason, then you must update the ``master_compute_data_rp

- First, run the test with ``pytest tests -k test_compute_everything`` and inspect the compute quantities whose values are in error, to ensure that only the quantities you expect to be different are shown (and that the new values are indeed the correct ones, you should have a test elsewhere for that though).
- If the values are as expected and only the expected compute quantities are different, then replace the block
- Then, if you have re-defined a variable, consider adding a ``DeprecationWarning`` to it to allow a grace period so old code
does not break, but is informed of the change. Add the old name an alias in the ``aliases`` part of the ``register_compute_function`` decorator,
and add to the ``deprecated_names`` dictionary in ``desc/compute/data_index.py`` the deprecated name as a key and the corresponding value as the new name for that variable.

.. code-block:: python

Expand Down
310 changes: 296 additions & 14 deletions desc/compute/_omnigenity.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,62 @@ def _nu(params, transforms, profiles, data, **kwargs):
return data


@register_compute_fun(
name="nu_B_mn",
label="\\nu_{mn} = (\\zeta_{B} - \\zeta)_{mn}",
units="rad",
units_long="radians",
description="Boozer harmonics of Boozer toroidal stream function",
dim=1,
params=[],
transforms={"B": [[0, 0, 0]], "grid": []},
profiles=[],
coordinates="rtz",
data=[
"sqrt(g)_Boozer_DESC",
"nu",
"rho",
"theta_B",
"zeta_B",
"Boozer transform modes norm",
],
resolution_requirement="tz",
grid_requirement={"is_meshgrid": True},
M_booz="int: Maximum poloidal mode number for Boozer harmonics. Default 2*eq.M",
N_booz="int: Maximum toroidal mode number for Boozer harmonics. Default 2*eq.N",
)
def _nu_B_mn(params, transforms, profiles, data, **kwargs):
norm = data["Boozer transform modes norm"]
grid = transforms["grid"]

def fun(rho, theta_B, zeta_B, sqrtg_B_desc, quant):
# this fits Boozer modes on a single surface
nodes = jnp.array([rho, theta_B, zeta_B]).T
quant_mn = (
norm # 1 if m=n=0, 2 if m=0 or n=0, 4 if m!=0 and n!=0
* (transforms["B"].basis.evaluate(nodes).T @ (sqrtg_B_desc * quant))
/ transforms["B"].grid.num_nodes
)
return quant_mn

def reshape(x):
return grid.meshgrid_reshape(x, "rtz").reshape((grid.num_rho, -1))

rho, theta_B, zeta_B, sqrtg_B_desc, nu = map(
reshape,
(
data["rho"],
data["theta_B"],
data["zeta_B"],
data["sqrt(g)_Boozer_DESC"],
data["nu"],
),
)
nu_B_mn = vmap(fun)(rho, theta_B, zeta_B, sqrtg_B_desc, nu)
data["nu_B_mn"] = nu_B_mn.flatten()
return data


@register_compute_fun(
name="nu_t",
label="\\partial_{\\theta} \\nu",
Expand Down Expand Up @@ -306,20 +362,22 @@ def _zeta_B(params, transforms, profiles, data, **kwargs):


@register_compute_fun(
name="sqrt(g)_B",
label="\\sqrt{g}_{B}",
name="sqrt(g)_Boozer_DESC",
f0uriest marked this conversation as resolved.
Show resolved Hide resolved
label="\\frac{\\partial(\\theta_B,\\zeta_B)}{\\theta_{DESC},\\zeta_{DESC}}",
units="~",
units_long="None",
description="Jacobian determinant from Boozer to DESC coordinates",
description="Jacobian determinant from Boozer coordinates (rho, theta_B, zeta_B)"
" to DESC coordinates (rho,theta,zeta).",
dim=1,
params=[],
transforms={},
profiles=[],
coordinates="rtz",
data=["theta_PEST_t", "theta_PEST_z", "phi_t", "phi_z", "nu_t", "nu_z", "iota"],
aliases=["sqrt(g)_B"],
)
def _sqrtg_B(params, transforms, profiles, data, **kwargs):
data["sqrt(g)_B"] = (
def _sqrt_g_Boozer_DESC(params, transforms, profiles, data, **kwargs):
data["sqrt(g)_Boozer_DESC"] = (
data["theta_PEST_t"] * (data["phi_z"] + data["nu_z"])
- data["theta_PEST_z"] * (data["phi_t"] + data["nu_t"])
+ data["iota"] * (data["nu_t"] * data["phi_z"] - data["nu_z"] * data["phi_t"])
Expand All @@ -328,7 +386,83 @@ def _sqrtg_B(params, transforms, profiles, data, **kwargs):


@register_compute_fun(
name="|B|_mn",
name="sqrt(g)_Boozer",
dpanici marked this conversation as resolved.
Show resolved Hide resolved
label="\\sqrt{g}_Boozer",
units="m^{3}",
units_long="cubic meters",
description="Jacobian determinant from (rho, theta_B, zeta_B)"
" Boozer coordinates to (R,phi,Z) lab frame.",
dim=1,
params=[],
transforms={},
profiles=[],
coordinates="rtz",
data=["sqrt(g)_Boozer_DESC", "sqrt(g)"],
)
def _sqrtg_B(params, transforms, profiles, data, **kwargs):
data["sqrt(g)_Boozer"] = data["sqrt(g)"] / data["sqrt(g)_Boozer_DESC"]
return data


@register_compute_fun(
name="sqrt(g)_Boozer_mn",
label="\\sqrt{g}_{B,mn}",
units="m^{3}",
units_long="cubic meters",
description="Boozer harmonics of Jacobian determinant from (rho, theta_B, zeta_B)"
" Boozer coordinates to (R,phi,Z) lab frame.",
dim=1,
params=[],
transforms={"B": [[0, 0, 0]], "grid": []},
profiles=[],
coordinates="rtz",
resolution_requirement="tz",
grid_requirement={"is_meshgrid": True},
data=[
"sqrt(g)_Boozer",
"sqrt(g)_Boozer_DESC",
"rho",
"theta_B",
"zeta_B",
"Boozer transform modes norm",
],
M_booz="int: Maximum poloidal mode number for Boozer harmonics. Default 2*eq.M",
N_booz="int: Maximum toroidal mode number for Boozer harmonics. Default 2*eq.N",
)
def _sqrtg_Boozer_mn(params, transforms, profiles, data, **kwargs):
norm = data["Boozer transform modes norm"]
grid = transforms["grid"]

def fun(rho, theta_B, zeta_B, sqrtg_B_desc, quant):
# this fits Boozer modes on a single surface
nodes = jnp.array([rho, theta_B, zeta_B]).T
quant_mn = (
norm # 1 if m=n=0, 2 if m=0 or n=0, 4 if m!=0 and n!=0
* (transforms["B"].basis.evaluate(nodes).T @ (sqrtg_B_desc * quant))
/ transforms["B"].grid.num_nodes
)
return quant_mn

def reshape(x):
return grid.meshgrid_reshape(x, "rtz").reshape((grid.num_rho, -1))

rho, theta_B, zeta_B, sqrtg_B_desc, sqrtg_B = map(
reshape,
(
data["rho"],
data["theta_B"],
data["zeta_B"],
data["sqrt(g)_Boozer_DESC"],
data["sqrt(g)_Boozer"],
),
)
sqrtg_B_mn = vmap(fun)(rho, theta_B, zeta_B, sqrtg_B_desc, sqrtg_B)
data["sqrt(g)_Boozer_mn"] = sqrtg_B_mn.flatten()
return data


@register_compute_fun(
name="|B|_mn_B",
dpanici marked this conversation as resolved.
Show resolved Hide resolved
label="B_{mn}^{\\mathrm{Boozer}}",
units="T",
units_long="Tesla",
Expand All @@ -338,35 +472,161 @@ def _sqrtg_B(params, transforms, profiles, data, **kwargs):
transforms={"B": [[0, 0, 0]], "grid": []},
profiles=[],
coordinates="rtz",
data=["sqrt(g)_B", "|B|", "rho", "theta_B", "zeta_B"],
data=[
"sqrt(g)_Boozer_DESC",
"|B|",
"rho",
"theta_B",
"zeta_B",
"Boozer transform modes norm",
],
resolution_requirement="tz",
grid_requirement={"is_meshgrid": True},
M_booz="int: Maximum poloidal mode number for Boozer harmonics. Default 2*eq.M",
N_booz="int: Maximum toroidal mode number for Boozer harmonics. Default 2*eq.N",
aliases=["|B|_mn"],
)
def _B_mn(params, transforms, profiles, data, **kwargs):
norm = 2 ** (3 - jnp.sum((transforms["B"].basis.modes == 0), axis=1))
norm = data["Boozer transform modes norm"]
grid = transforms["grid"]

def fun(rho, theta_B, zeta_B, sqrtg_B, B):
def fun(rho, theta_B, zeta_B, sqrtg_B_desc, quant):
# this fits Boozer modes on a single surface
nodes = jnp.array([rho, theta_B, zeta_B]).T
B_mn = (
norm # 1 if m=n=0, 2 if m=0 or n=0, 4 if m!=0 and n!=0
* (transforms["B"].basis.evaluate(nodes).T @ (sqrtg_B * B))
* (transforms["B"].basis.evaluate(nodes).T @ (sqrtg_B_desc * quant))
/ transforms["B"].grid.num_nodes
)
return B_mn

def reshape(x):
return grid.meshgrid_reshape(x, "rtz").reshape((grid.num_rho, -1))

rho, theta_B, zeta_B, sqrtg_B, B = map(
rho, theta_B, zeta_B, sqrtg_B_desc, B = map(
reshape,
(data["rho"], data["theta_B"], data["zeta_B"], data["sqrt(g)_B"], data["|B|"]),
(
data["rho"],
data["theta_B"],
data["zeta_B"],
data["sqrt(g)_Boozer_DESC"],
data["|B|"],
),
)
B_mn = vmap(fun)(rho, theta_B, zeta_B, sqrtg_B_desc, B)
data["|B|_mn_B"] = B_mn.flatten()
return data


@register_compute_fun(
name="R_mn_B",
label="R_{mn}^{\\mathrm{Boozer}}",
units="m",
units_long="meters",
description="Boozer harmonics of radial toroidal coordinate of a flux surface",
dim=1,
params=[],
transforms={"B": [[0, 0, 0]], "grid": []},
profiles=[],
coordinates="rtz",
resolution_requirement="tz",
grid_requirement={"is_meshgrid": True},
data=[
"R",
"sqrt(g)_Boozer_DESC",
"rho",
"theta_B",
"zeta_B",
"Boozer transform modes norm",
],
M_booz="int: Maximum poloidal mode number for Boozer harmonics. Default 2*eq.M",
N_booz="int: Maximum toroidal mode number for Boozer harmonics. Default 2*eq.N",
)
def _R_mn(params, transforms, profiles, data, **kwargs):
norm = data["Boozer transform modes norm"]
grid = transforms["grid"]

def fun(rho, theta_B, zeta_B, sqrtg_B_desc, quant):
# this fits Boozer modes on a single surface
nodes = jnp.array([rho, theta_B, zeta_B]).T
quant_mn = (
norm # 1 if m=n=0, 2 if m=0 or n=0, 4 if m!=0 and n!=0
* (transforms["B"].basis.evaluate(nodes).T @ (sqrtg_B_desc * quant))
/ transforms["B"].grid.num_nodes
)
return quant_mn

def reshape(x):
return grid.meshgrid_reshape(x, "rtz").reshape((grid.num_rho, -1))

rho, theta_B, zeta_B, sqrtg_B_desc, R = map(
reshape,
(
data["rho"],
data["theta_B"],
data["zeta_B"],
data["sqrt(g)_Boozer_DESC"],
data["R"],
),
)
R_mn = vmap(fun)(rho, theta_B, zeta_B, sqrtg_B_desc, R)
data["R_mn_B"] = R_mn.flatten()
return data


@register_compute_fun(
name="Z_mn_B",
label="Z_{mn}^{\\mathrm{Boozer}}",
units="m",
units_long="meters",
description="Boozer harmonics of vertical coordinate of a flux surface",
dim=1,
params=[],
transforms={"B": [[0, 0, 0]], "grid": []},
profiles=[],
coordinates="rtz",
resolution_requirement="tz",
grid_requirement={"is_meshgrid": True},
data=[
"Z",
"sqrt(g)_Boozer_DESC",
"rho",
"theta_B",
"zeta_B",
"Boozer transform modes norm",
],
M_booz="int: Maximum poloidal mode number for Boozer harmonics. Default 2*eq.M",
N_booz="int: Maximum toroidal mode number for Boozer harmonics. Default 2*eq.N",
)
def _Z_mn(params, transforms, profiles, data, **kwargs):
norm = data["Boozer transform modes norm"]
grid = transforms["grid"]

def fun(rho, theta_B, zeta_B, sqrtg_B_desc, quant):
# this fits Boozer modes on a single surface
nodes = jnp.array([rho, theta_B, zeta_B]).T
quant_mn = (
norm # 1 if m=n=0, 2 if m=0 or n=0, 4 if m!=0 and n!=0
* (transforms["B"].basis.evaluate(nodes).T @ (sqrtg_B_desc * quant))
/ transforms["B"].grid.num_nodes
)
return quant_mn

def reshape(x):
return grid.meshgrid_reshape(x, "rtz").reshape((grid.num_rho, -1))

rho, theta_B, zeta_B, sqrtg_B_desc, Z = map(
reshape,
(
data["rho"],
data["theta_B"],
data["zeta_B"],
data["sqrt(g)_Boozer_DESC"],
data["Z"],
),
)
B_mn = vmap(fun)(rho, theta_B, zeta_B, sqrtg_B, B)
data["|B|_mn"] = B_mn.flatten()
Z_mn = vmap(fun)(rho, theta_B, zeta_B, sqrtg_B_desc, Z)
data["Z_mn_B"] = Z_mn.flatten()
return data


Expand All @@ -390,6 +650,28 @@ def _B_modes(params, transforms, profiles, data, **kwargs):
return data


@register_compute_fun(
name="Boozer transform modes norm",
label="",
units="~",
units_long="None",
description="Inner product norm for boozer modes basis. This norm is used as a"
"weight when performing the integral of the Boozer transform to get the "
"correct Boozer Fourier amplitudes.",
dim=1,
params=[],
transforms={"B": [[0, 0, 0]]},
profiles=[],
coordinates="rtz",
data=[],
)
def _boozer_modes_norm(params, transforms, profiles, data, **kwargs):
# norm is 1 if m=n=0, 2 if m=0 or n=0, 4 if m!=0 and n!=0
norm = 2 ** (3 - jnp.sum((transforms["B"].basis.modes == 0), axis=1))
data["Boozer transform modes norm"] = norm
return data


@register_compute_fun(
name="f_C",
label="[(M \\iota - N) (\\mathbf{B} \\times \\nabla \\psi)"
Expand Down
Loading
Loading